https://github.com/apaleslimghost/excise
a react-like toolkit for web components
https://github.com/apaleslimghost/excise
custom-elements diffhtml react shadow-dom
Last synced: 7 months ago
JSON representation
a react-like toolkit for web components
- Host: GitHub
- URL: https://github.com/apaleslimghost/excise
- Owner: apaleslimghost
- Created: 2016-10-02T21:08:47.000Z (about 9 years ago)
- Default Branch: master
- Last Pushed: 2021-01-20T17:09:11.000Z (over 4 years ago)
- Last Synced: 2025-03-17T14:07:42.796Z (7 months ago)
- Topics: custom-elements, diffhtml, react, shadow-dom
- Language: JavaScript
- Homepage:
- Size: 48.8 KB
- Stars: 7
- Watchers: 0
- Forks: 3
- Open Issues: 0
-
Metadata Files:
- Readme: readme.md
Awesome Lists containing this project
README
# excise
a toolkit for writing functional-style (react-like) web components, based on [diffhtml](https://github.com/tbranyen/diffhtml)
## install
```sh
npm install excise
```Or give it a try using [this JSBin](https://jsbin.com/qecuhigisu/edit?html,js,output) in Chrome.
## usage
### basic
you'll need a browser that supports custom elements v1 and shadow dom v1. chrome 55 will work.
```js
const {define, html} = require('excise');define('x-hello-world', () => html`
it works!
`);document.body.innerHTML = '';
```#### polyfills
the only polyfills i've found that work are [custom-elements](https://github.com/webcomponents/custom-elements) and [shadydom](https://github.com/webcomponents/shadydom). they're not fully on npm yet but they can be installed with:
```sh
npm install --save webcomponents/shadydom webcomponents/custom-elements
```and then include them with
```js
require('@webcomponents/shadydom');
require('@webcomponents/custom-elements');
```or as entry points to your bundle
#### bundling
i've found it difficult to get this working with webpack because it thinks `define` means AMD and even if you disable that plugin it breaks. just use browserify, and don't bother with babel because we need to natively extend `HTMLElement`.
### props
element attributes are passed as an object to the render function
```js
const {define, html} = require('excise');define('x-count', ({count}) => html`
${count}
`);document.body.innerHTML = '';
```pass a third argument to `define` to specify the types of the props, for coercion:
```js
const {define, html, types} = require('excise');define('x-increment', ({count}) => html`
${count + 1}
`, {count: types.number});document.body.innerHTML = '';
```### server rendering
call `renderToString` with an `html` block:
```js
const {define, html, renderToString} = require('excise');define('x-foo', () => html`
hello
`);renderToString(html``); //⇒
hello
```the extra `span` allows you to reuse the server-rendered markup on the client. when your elements are defined, the `__excise_rendered` slot is ignored.
### events
`on*` attributes are attached to elements as event handlers:
```js
const {define, html} = require('excise');define('x-button', () => html` alert('hello!')}>click me`);
document.body.innerHTML = '';
```### state
`StatefulComponent` watches its attributes and rerenders when they change:
```js
const {StatefulComponent, html, types} = require('excise');StatefulComponent.define('x-counter',
(props, el) => html`${props.count} el.setAttribute('count', props.count + 1)}>click me}`,
{count: types.number}
);document.body.innerHTML = '';
```there's a little bit of oddness here. we can't destructure `count` here like in previous examples, because of how diffhtml renders the button. the actual dom of the button never changes (it's the same structure) so diffhtml leaves it alone when `count` updates. this means the `onclick` handler still closes over `count` from the first run of the render function, and the button only works once.
### shadow dom/slots
```js
const {define, html} = require('excise');define('x-shadow', () => html`
slots work
`);document.body.innerHTML = '
it works!
';
```### classes
```js
const {Component, html, types} = require('excise');define(class XClassComponent extends Component {
static get propTypes() {
return {
greeting: types.string,
};
}render() {
return html`it works! ${this.props.greeting}
`;
}
});document.body.innerHTML = ''
```## licence
ISC. © kara brightwell