This is not yet another minimalistic React implementation, the primary use case is to create actual dom with a single function and JSX directly, but there're opt-in component lifecycle hooks.
This lib does not accept pull requests for new features since the primary use case (get actual DOM from JSX) is already set for good.
- Insanely small: 2kB minified
- One API: JSX is transformed to vNode, use
mount(vNode)
to get actual DOM. - SVG support
- Protection from XSS injections
- Automatically joining classNames, styles
yarn add dom-dom
With a transpiler like babel+babel-plugin-transform-react-jsx
or typescript
or buble
:
/* @jsx h */
import { h, mount } from 'dom-dom/tiny'
// With only first arg
const button = mount(<button>click me</button>)
// button.outerHTML:
// => '<button>click me</button>'
// With second arg
// replacce `#root` with created element
mount(
<button>hello</button>,
document.getElementById('root')
)
Note that while using CDN version you can access d2.h
d2.mount
instead.
className
can be string
Array
or Object
:
<div className="foo"></div>
<div className={['foo', 'bar']}></div>
<div className={{foo: false, [`bar-${index}`]: true}}></div>
You can also directly use class
instead of react-specific className
as you please:
<div class="foo"></div>
style
supports string
and Object
:
<div style="color: red"></div>
// both kebab-case and camelCase are supported here
// default unit is `px`
<div style={{ fontSize: 14, 'background-color': 'red' }}></div>
<div dangerouslySetInnerHTML={{__html: '<strong>hey</strong>'}}></div>
React-like events are supports:
<button onClick={handleClick}></button>
WARNING: If you only want a function to transform vNode to actual dom, please stop reading!!! Above features would be enough for your use case. Following features may not be what you want :D To use full build you should
import { xxx } from 'dom-dom'
instead.
Create your own React with dom-dom
// @jsx h
import { h, mount, unmount } from 'dom-dom'
class Component {
setState(state) {
if (typeof state === 'function') {
state = state(this.state)
}
for (const key in state) {
this.state[key] = state[key]
}
this.mount()
}
mount(root = this.$root) {
this.$root = mount(this, root)
return this.$root
}
destroy = () => {
unmount(this, this.$root)
}
}
class Counter extends Component {
state = { count: 0 }
handleClick = () => {
this.setState(prevState => ({
count: prevState.count + 1
}))
}
componentDidMount() {
console.log('app mounted!', this)
}
render() {
return (<div>
<button onClick={this.handleClick}>
clicked: {this.state.count} times
</button>
<button onClick={this.destroy}>destroy</button>
</div>)
}
}
const counter = new Counter()
counter.mount(document.getElementById('root'))
You can mount
unmount
a object or class instance which has a render
method that returns vNode
.
import { h, mount } from 'dom-dom'
const A = {
render() {
return <div>a</div>
}
}
const B = class {
render() {
return <div>{A}</div>
}
}
mount(new B, document.getElementById('root'))
Object and class instance with render function can also be one of your JSX children.
This is designed for using lifecycle hooks, currently we have componentDidMount
componentWillMount
and componentWillUnmount
.
const App = {
componentDidMount() {
console.log('hi')
},
componentWillUnmount() {
console.log('bye')
},
render() {
return <div>hi</div>
}
}
const root = mount(App, document.getElementById('root'))
//=> hi
unmount(App, root)
//=> bye
This project is heavily inspired by preact and dom-chef.
- Fork it!
- Create your feature branch:
git checkout -b my-new-feature
- Commit your changes:
git commit -am 'Add some feature'
- Push to the branch:
git push origin my-new-feature
- Submit a pull request :D
dom-dom © egoist, Released under the MIT License.
Authored and maintained by egoist with help from contributors (list).
egoistian.com · GitHub @egoist · Twitter @_egoistlily