LoginSignup
16
15

More than 5 years have passed since last update.

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

Posted at

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

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

Mount

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

ComponentNode

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

パフォーマンス

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

test.jpg

手元の環境 (OS X 10.10.1 + Chrome 39) だとなぜかTodoMVCでいい感じのパフォーマンス(一番下)が出ます(バグかもしれませんが…)
機能を増やしたり使い勝手をよくしていくとどうなるかは今のところわかりません。

まとめ

  • virtual-domベースで単純なコンポーネントシステムを簡単に作ることができた
  • パフォーマンスも結構出るっぽい?
16
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
15