仮想DOMを使ったJavaScriptライブラリまとめ
ここ数年JavaScript界隈で注目を集めたのがVirtual DOM(仮想DOM)です。DOMをJavaScriptから操作する場合、その状態を管理するのが問題になりますが、Virtual DOMではDOMの描画から開放されるのでロジックとビューの分離が可能になります。
そんなVirtual DOMを提供するライブラリを紹介します。
React – A JavaScript library for building user interfaces
Virtual DOMを最初に広めたのがReactです。画期的な概念であり、JavaScriptプログラマにとって大きな変革になりました。次期バージョンからReact Fiberとなり、レンダリング処理などが高速化すると言われています。
元々Virtual DOMによってDOMとは切り離された技術になっていますので、React Nativeによってスマートフォンアプリの描画に使われたり、コミュニティベースではReact CanvasでCanvasへの描画、React Consoleというコンソールアプリケーション開発用のソフトウェアも作られています。
React – A JavaScript library for building user interfaces
Vue.js
Reactが独自のタグを定義するのに対してVue.jsでは元々のHTMLタグを活用したVirtual DOM利用ができます。そのため学習コストが低く、利用者が増えています。Reactと同じようにサーバサイドレンダリングにも対応しています。
シンプルな仕組みで、ランタイムもコンパクトです。Virtual DOMの仕組みも高速なのが売りです。
Maquette
ReactはJSXを覚える必要がありますが、Maquetteは純粋なJavaScriptだけで記述できます。以下はサンプルコードです。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var yourName = ''; // Piece of data | |
// Plain event handler | |
function handleNameInput(evt) { | |
yourName = evt.target.value; | |
} | |
// This function uses the 'hyperscript' notation to create the virtual DOM. | |
function renderMaquette() { | |
return h('div', [ | |
h('input', { | |
type: 'text', placeholder: 'What is your name?', | |
value: yourName, oninput: handleNameInput | |
}), | |
h('p.output', ['Hello ' + (yourName || 'you') + '!']) | |
]); | |
} | |
projector.append(domNode, renderMaquette); |
GZip圧縮すると3KBになるというコンパクトなサイズも売りです。
Preact | Preact: Fast 3kb React alternative with the same ES6 API. Components & Virtual DOM.
Reactの代替と銘打っているライブラリです。React向けに作られているコンポーネントがそのまま使えるようになっているのがポイントです。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export default class TodoList extends Component { | |
state = { todos: [], text: '' }; | |
setText = e => { | |
this.setState({ text: e.target.value }); | |
}; | |
addTodo = () => { | |
let { todos, text } = this.state; | |
todos = todos.concat({ text }); | |
this.setState({ todos, text: '' }); | |
}; | |
render({ }, { todos, text }) { | |
return ( | |
<form onSubmit={this.addTodo} action="javascript:"> | |
<input value={text} onInput={this.setText} /> | |
<button type="submit">Add</button> | |
<ul> | |
{ todos.map( todo => ( | |
<li>{todo.text}</li> | |
)) } | |
</ul> | |
</form> | |
); | |
} | |
} |
パフォーマンスやサイズに重点を置いており、Reactを使っている方の悩みを解決する存在と言えそうです。
Preact | Preact: Fast 3kb React alternative with the same ES6 API. Components & Virtual DOM.
WebReflection/hyperHTML: A Fast & Light Virtual DOM Alternative
hyperHTMLはシンプルなVirtual DOMライブラリとなっています。onclickなどは別な関数を定義して、そちらに飛ばす仕組みになっています。以下はサンプルコードです。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// this is hyperHTML | |
function tick(render) { | |
render` | |
<div> | |
<h1>Hello, world!</h1> | |
<h2>It is ${new Date().toLocaleTimeString()}.</h2> | |
</div> | |
`; | |
} | |
setInterval(tick, 1000, | |
hyperHTML.bind(document.getElementById('root')) | |
); |
WebReflection/hyperHTML: A Fast & Light Virtual DOM Alternative
anthonyshort/deku: Render interfaces using pure functions and virtual DOM
Reduxと組み合わせて使うこともできるVirtual DOMライブラリです。軽量なReactといった雰囲気があります。ピュアなJavaScriptで記述できるのがポイントです。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** @jsx element */ | |
import {element, createApp} from 'deku' | |
import {createStore} from 'redux' | |
import reducer from './reducer' | |
// Dispatch an action when the button is clicked | |
let log = dispatch => event => { | |
dispatch({ | |
type: 'CLICKED' | |
}) | |
} | |
// Define a state-less component | |
let MyButton = { | |
render: ({ props, children, dispatch }) => { | |
return <button onClick={log(dispatch)}>{children}</button> | |
} | |
} | |
// Create a Redux store to handle all UI actions and side-effects | |
let store = createStore(reducer) | |
// Create an app that can turn vnodes into real DOM elements | |
let render = createApp(document.body, store.dispatch) | |
// Update the page and add redux state to the context | |
render( | |
<MyButton>Hello World!</MyButton>, | |
store.getState() | |
) |
Reactで書いた場合の半分くらいのサイズになるようです。
anthonyshort/deku: Render interfaces using pure functions and virtual DOM
Virtual DOMはWebアプリケーションが大型化していく中で見逃せない概念になっています。かといってReactやVue.jsで開発するのに苦痛を感じる方もいるでしょう。そうした時にはVirtual DOMのライブラリを採用するのも手でしょう。
DOMの状態管理が大変になってきていたら導入を検討してみてはいかがでしょう。
コメントは受け付けていません。