All Projects → tweedjs → Tweed

tweedjs / Tweed

Licence: wtfpl
An Object Oriented UI Library

Programming Languages

javascript
184084 projects - #8 most used programming language
typescript
32286 projects

Labels

Projects that are alternatives of or similar to Tweed

joltik
A really small VDOM library
Stars: ✭ 40 (+29.03%)
Mutual labels:  vdom
Preact Habitat
Zero configuration Preact widgets renderer in any host DOM
Stars: ✭ 444 (+1332.26%)
Mutual labels:  vdom
Nerv
A blazing fast React alternative, compatible with IE8 and React 16.
Stars: ✭ 5,409 (+17348.39%)
Mutual labels:  vdom
zaftig
~2kB css in js: z`display flex` // .zjsdkk43-1
Stars: ✭ 15 (-51.61%)
Mutual labels:  vdom
Lowlight
Virtual syntax highlighting for virtual DOMs and non-HTML things
Stars: ✭ 310 (+900%)
Mutual labels:  vdom
Hyperawesome
A curated list of awesome projects built with Hyperapp & more.
Stars: ✭ 446 (+1338.71%)
Mutual labels:  vdom
Inferno
🔥 An extremely fast, React-like JavaScript library for building modern user interfaces
Stars: ✭ 15,206 (+48951.61%)
Mutual labels:  vdom
Muve
Muve is a micro library for building interactive javascript applications.
Stars: ✭ 11 (-64.52%)
Mutual labels:  vdom
Hyperapp
The tiny framework for building hypertext applications.
Stars: ✭ 18,724 (+60300%)
Mutual labels:  vdom
Domvm
DOM ViewModel - A thin, fast, dependency-free vdom view layer
Stars: ✭ 581 (+1774.19%)
Mutual labels:  vdom
impex
a powerful web application engine
Stars: ✭ 74 (+138.71%)
Mutual labels:  vdom
Fard
🎃 Multi thread javascript framework - 多线程小程序引擎
Stars: ✭ 310 (+900%)
Mutual labels:  vdom
Ijk
Transforms arrays into virtual dom trees; a terse alternative to JSX and h
Stars: ✭ 452 (+1358.06%)
Mutual labels:  vdom
vdom
Simple JavaScript Virtual DOM
Stars: ✭ 17 (-45.16%)
Mutual labels:  vdom
Backbone.vdomview
VirtualDOM-aware Backbone View
Stars: ✭ 23 (-25.81%)
Mutual labels:  vdom
purescript-outwatch
A functional and reactive UI framework based on Rx and VirtualDom
Stars: ✭ 33 (+6.45%)
Mutual labels:  vdom
Ivi
🔥 Javascript (TypeScript) library for building web user interfaces
Stars: ✭ 445 (+1335.48%)
Mutual labels:  vdom
Preact
⚛️ Fast 3kB React alternative with the same modern API. Components & Virtual DOM.
Stars: ✭ 30,527 (+98374.19%)
Mutual labels:  vdom
Puddles
Tiny vdom app framework. Pure Redux. No boilerplate.
Stars: ✭ 24 (-22.58%)
Mutual labels:  vdom
Vhtml
Render JSX/Hyperscript to HTML strings, without VDOM 🌈
Stars: ✭ 556 (+1693.55%)
Mutual labels:  vdom

Tweed

Tweed is a UI library similar to React, but in an object oriented style.


Installing

$ npm install tweed

Or with CLI:

$ npm install --global tweed-cli
$ tweed new my-blog

Overview

Here is what a Counter looks like:

// src/Counter.js

import { mutating, VirtualNode } from 'tweed'

export default class Counter {
  @mutating _times = 0

  render () {
    return (
      <button on-click={() => this._times++}>
        Clicked {this._times} times
      </button>
    )
  }
}

Rendering

// src/main.js

import render from 'tweed/render/dom'
import Counter from './Counter'

render(new Counter(), document.querySelector('#app'))

Server side rendering

Rendering on the server works exactly the same, but instead of mounting the Virtual DOM on the actual DOM, we want to render the app once into a string. This can be accomplished with the StringRenderer which takes a function (html: string) => void as its single constructor argument, which can then be hooked up to any server. The StringRenderer is available at 'tweed/render/string'.

// src/main.js

import render from 'tweed/render/string'
import Counter from './Counter'

render(new Counter(), (html) => {
  res.writeHead(200, { 'Content-Type': 'text/html' })
  res.end(html)
})

Why?

So why does the world need yet another JavaScript UI library? Tweed attempts to solve a very specific "problem" with React, if you're used to object oriented program architecture.

The problem

React uses a top-down functional reactive architecture, with a narrow focus on pure functions and a one-way data flow. Component A renders Component B, which renders Component C in turn. To make components reusable, all components implicitly receives a list of children components, which they can choose whether or not to render.

const MyComponentTakesChildren = ({ children }) => (
  <div>{children}</div>
)
const MyComponentDoesnt = () => (
  <div>Hard Coded!</div>
)

If a component needs to distinguish between multiple passed down components, it can just as well receive components as props:

<MyComponent
  childA={<div>Child A</div>}
  childB={<div>Child A</div>}
/>

Although this results in JSX which is quite far from semantic HTML. Furthermore, if a component needs to polymorphically send properties to a child, the solution is to send down the component constructor:

const MyComponent = ({ child: Child }) => (
  <Child polymorphic='value' />
)

<MyComponent
  child={SpecialChild}
/>

Ultimately, we end up with confusing JSX which doesn't really encourage you to value polymorphism and restrictions on source code dependencies.

Object Oriented programming teaches us to decouple code by hiding implementation and depending on abstractions.

Tweed doesn't treat components as nodes in the Virtual DOM, but simply lets you organize your UI in an OOP style dependency tree, which then collectively renders the v-dom.

interface Greeting {
  greet (name: string): VirtualNode
}

class Greeter {
  constructor (
    private readonly _greeting: Greeting
  ) {}

  render () {
    return <div>{this._greeting.greet('World')}</div>
  }
}

class BasicGreeting implements Greeting {
  greet (name: string) {
    return <h1>Hello {name}</h1>
  }
}

class CoolGreeting implements Greeting {
  greet (name: string) {
    return <h1>Yo {name}</h1>
  }
}

new Greeter(new BasicGreeting()).render() // => <div><h1>Hello World</h1></div>
new Greeter(new CoolGreeting()).render() // => <div><h1>Yo World</h1></div>

Note that the above example is completely stateless. We have no assignments. We also have no inheritance, only object oriented composition.

In OOP, we know to be careful about state, and to make it clear what is mutable and what's not. Tweed requires you to be explicit about mutable properties, albeit for technical reasons.

class Counter {
  @mutating private _count = 0

  render () {
    return (
      <button on-click={() => this._count++}>
        Clicked {this._count} times
      </button>
    )
  }
}

As a user, you are responsible for creating all the instances of the classes before Tweed mounts them to the DOM. Those instances are then persistent, as opposed to with React, where class components are reinstantiated on every render (if not handled differently with mechanisms like shouldComponentUpdate).

This is a performance benefit, because for every state change, update, and repaint, it boils down to a simple call to render on the root component. It's the equivalent of calling toString but for VDOM nodes instead of strings. And no data is being passed either. The state of the tree is persistent as well. Deciding to opt for a more functional and immutable way of managing state is entirely up to you.


You can read more about the architecture of a Tweed app here.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].