Posted at

virtual-domを使って、Reactみたいなコンポーネントを実現するライブラリを書いてみた

More than 3 years have passed since last update.

Virtual DOM がアツい昨今ですが、virtual DOM は特に Reactdekuのようなコンポーネントライブラリの実装に使われているということで注目を集めています。

一方、virtual DOM自体は概念にすぎないので、それを独立して実装しているvirtual-domなどのライブラリもあります (以前の記事で書きました)。

そこで、その virtual-dom をベースにReactのようなコンポーネントライブラリを自作してみるのも興味深いと思い試してみました。


作ったものの概要

seanchas116/decompose


  • virtual-dom ベース

  • ビューと状態を一つにまとめたコンポーネント


    • 簡単化のためにstates/propsの区別はなし



  • 同じ場所/移動しているが同じキー の時は同一コンポーネントがそのまま生き残る

  • 各コンポーネントごとに独立してdiff/patch


    • パフォーマンスのため。見たところdekuも同じことをやっている (Reactは大きすぎて今のところ読めていない…)

    • これは素のvirtual-domだとやりにくく、virtual-domのWidgetノードをうまく使うと実装できる

    • Reactと違って、外側のコンポーネントが更新された時に内側のコンポーネントも更新されるようにはしていない (パフォーマンスは良くなるけど使い勝手は悪くなるかも?)



  • 本物のDOMをコンポーネントとして扱うこともできる

(今のところ)CoffeeScriptで200行程度のかなり簡単な実装です。

今のところ、CoffeeScriptのクラスを使いまくっているので、ES5以前のJSで使うとつらそうです。


{Component} = require 'decompose'

class TodoView extends Component

render: ->
h 'li', [
h 'h2', @todo.title
]

class TodoListView extends Component

render: ->
h 'ul', @todos.map (todo) =>
TodoView.render todo: todo

todoListView = new TodoListView(todos: todoCollection.todos)
todoCollection.on 'update', ->
todoListView.update()

new Mount(todoListView).mount('#main')


TodoMVC

定番のTodoMVC実装をこのライブラリでも書いてみました。

seanchas116/decompose-todomvc


実装


Component

コンポーネントのベースクラスです。

https://github.com/seanchas116/decompose/blob/master/src/component/Component.coffee


Mount

実DOM上にマウントします。1イベントループ中にComponentがupdateイベントを1回以上吐くと、イベントループ完了時にdiff/patchが行われます。

https://github.com/seanchas116/decompose/blob/master/src/mount/Mount.coffee


ComponentNode

virtual-domのdiff/patch用に使われます。

https://github.com/seanchas116/decompose/blob/master/src/node/ComponentNode.coffee


パフォーマンス

https://github.com/seanchas116/todomvc-perf-comparison

(@dsuket さんの https://github.com/dsuket/todomvc-perf-comparison をフォークさせていただきました)

test.jpg

手元の環境 (OS X 10.10.1 + Chrome 39) だとなぜかTodoMVCでいい感じのパフォーマンス(一番下)が出ます(バグかもしれませんが…)

機能を増やしたり使い勝手をよくしていくとどうなるかは今のところわかりません。


まとめ


  • virtual-domベースで単純なコンポーネントシステムを簡単に作ることができた

  • パフォーマンスも結構出るっぽい?