An open API service indexing awesome lists of open source software.

https://github.com/evolutionjobs/polymer-vdom

Virtual DOM builder for Polymer
https://github.com/evolutionjobs/polymer-vdom

dom jsx polymer polymer-components polymer-vdom shadow-dom

Last synced: 7 days ago
JSON representation

Virtual DOM builder for Polymer

Awesome Lists containing this project

README

        

# Polymer VDOM

I like React, especially its core idea of Virtual DOM - objects that represent the DOM and can be merged with it rapidly, allowing it to quickly and easily build and alter large amounts of HTML. React uses JSX tools to build low level JS.

I like Polymer, expecially its core idea of **#UseThePlatform** - it extends and shims web components and shadow DOM to make them easier to build modular applications. Polymer doesn't help with building lots of dynamic HTML content - `dom-if` and `dom-repeat` templates are useful, but painful where a lot of content can change.

React has its own component model; Polymer uses the platform's component model. It seems to make a lot of sense to use the component model that's actually built into the browser, rather than a proprietary one (even if it's good, and React's is).

Polymer components can be used (to some extent) in React JSX, but not the other way round (though you can add wrappers to achieve this), and there are a couple of conflicts. Downloading all of React (or even Preact) just to use the JSX VDOM builder is a lot of overhead.

The goal of this project is to use JSX tools (where appropriate) to build the shadow DOM in Polymer components, with minimal overhead.

## Demo

`` has a [sample version](https://github.com/EvolutionJobs/calendrical-heatmap/blob/master/calendrical-heatmap.tsx) written using this.

## Set Up

For TypeScript `*.tsx` support include [`builder.ts`](Builder.ts) and [`polymer-vdom.ts`](polymer-vdom.js), and set `tsconfig.json` to tell `tsc` to output `h` when parsing JSX:

```json
{
"compilerOptions": {
"jsx": "react",
"jsxFactory": "h"
}
}
```

For JSX `*.jsx` support include [`polymer-vdom.js`](polymer-vdom.js), and update `.babelrc` (assuming Babel 6):

```json
{
"plugins": [
["transform-react-jsx", { "pragma":"h" }]
]
}
```

These are the same settings as for Preact, the the config are interchangeable.

## Example

Use the mixin `WithVdom` around `Polymer.Element`, `HTMLElement` or whatever you want to extend.
Inside that class you can use `render` to output JSX into the attached shadow DOM:

```js
import WithVdom from './polymer-vdom.js'
class VdomTest extends WithVdom(Polymer.Element) {
static get is() { return 'vdom-test'; }

ready() {
super.ready();
super.render(

The time is {new Date()}
);
}
}

customElements.define(VdomTest.is, VdomTest);
```

Each time `render()` is called the shadow DOM root is updated with the new JSX content, following the same rules as React for keys:

```js
super.render(


  • B

  • C

);

// This will add the "a"

  • and remove the "c", rather than update two nodes
    super.render(

    • A

    • B

    );
    ```

    Where this differs from React is the component model - names of component classes wll be ignored. Instead use any tags registered with `customElements.define`:

    ```js
    // Bad
    super.render(

    );

    // Good #usetheplatform
    super.render(

    );
    ```

    At the moment this code needs to be in a `*.tsx`|`*.jsx` file. Next step will be build tools to add the JSX output to a `` tag in and HTML import.

    Events can use Preact inline (`onclick`) or Polymer hyphens (`on-click`).
    However, web components also allow mixed case events, which means React's camelCase (`onClick`) is not supported.

    ## Using Without JSX

    You can render VDOM without the JSX step:

    ```js
    // Using VDOM objects
    super.render({
    type: 'ul',
    props: {
    children: [
    { type: 'li', props: { key: 'a', children: 'A' } },
    { type: 'li', props: { key: 'b', children: 'B' } }
    ]
    })

    // Or function calls JSX outputs to
    super.render(
    h('ul', null
    h('li', { key: 'a' }, 'A'),
    h('li', { key: 'b' }, 'B'))
    ```

    It's recommended to use TypeScript (or some other type checker) if doing this to find errors at compile time.
    Implement `JSX.Element` from [JSX.d.ts](JSX.d.ts).