Mithril 1.1.0

自動再描画システム

Mithrilは、高速なレンダリングのために仮想DOM差分システムを実装しています。また、それに加えてアプリケーションがレンダリングをコントロールできるように、適切な粒度のさまざまなメカニズムを提供しています。

慣用的な表現をすると、Mithrilはデータレイヤーの変更をDOMに同期するために、自動再描画システムを利用しています。自動再描画システムはm.mount()、もしくはm.route()関数を使うと有効化されます。m.render()呼び出しを使って画面更新を行うとこの機能は無効なままです。

自動再描画システムは単純に、特定の関数の実行が完了したら再描画関数が実行されるようになっています。

イベントハンドラ後

Mithrilは、Mithrilのビューで定義されたDOMイベントハンドラの実行後に再描画を自動で行います:

var MyComponent = {
    view: function() {
        return m("div", {onclick: doSomething})
    }
}

function doSomething() {
    // この関数の実行直後に同期的に再描画が行われる
}

m.mount(document.body, MyComponent)

特定のイベントの再描画を無効にするには、e.redrawfalseを設定します。

var MyComponent = {
    view: function() {
        return m("div", {onclick: doSomething})
    }
}

function doSomething(e) {
    e.redraw = false
    // このdivがクリックされても再描画は行われない
}

m.mount(document.body, MyComponent)

m.request後

Mithrilはm.requestの処理が完了した後に自動で再描画を行います:

m.request("/api/v1/users").then(function() {
    // この関数の実行後に再描画が発生
})

特定のサーバーリクエスト処理後に再描画を無効にするには、backgroundオプションをtrueにします:

m.request("/api/v1/users", {background: true}).then(function() {
    // 再描画は行われない
})

ラウトの変更後

Mithrilはm.route.set()を呼び出したり、m.route.linkを使用したリンクをクリックした後に再描画を自動で行います:

var RoutedComponent = {
    view: function() {
        return [
            // ラウと変更後に同期的に再描画が実行
            m("a", {href: "/", oncreate: m.route.link}),
            m("div", {
                onclick: function() {
                    m.route.set("/")
                }
            }),
        ]
    }
}

m.route(document.body, "/", {
    "/": RoutedComponent,
})

Mithrilが再描画を行わない時

MithrilはsetTimeout, setInterval, requestAnimationFrameの呼び出し、Promise、サードパーティーライブラリが提供するイベントハンドラ(例: Socket.ioのコールバック)では再描画を行いません。この場合は、手動で<a3><c4>m.redraw()</c4></a3>を呼び出す必要があります。

Mithrilはライフサイクルメソッド後にも再描画は行いません。UIの一部はoninitハンドラの後に再描画されますが、UIの他の部分は指定のoninitハンドラが起動した時にすでに再描画されているでしょう。oncreateonupdateハンドラはUIが再描画された後に呼ばれます。

ライフサイクルメソッド内で再描画を明示的に行う時はm.redraw()を呼びます。この関数は非同期で再描画を行います。

var StableComponent = {
    oncreate: function(vnode) {
        vnode.state.height = vnode.dom.offsetHeight
        m.redraw()
    },
    view: function() {
        return m("div", "このコンポーネントの高さは " + vnode.state.height + "ピクセルです")
    }
}

Mithrilはm.renderで描画されたvnodeツリーの再描画は行いません。m.renderを使ってレンダリングされたテンプレートに対しては、イベントの変更やm.requestの呼び出しでは再描画は行われません。そのため、Reduxのようなライブラリを使っている場合など、アーキテクチャの都合上、描画の制御をマニュアルで行う必要があれば、m.mountの代わりにm.renderを使うべきです。

m.renderはvnodeツリーを受け取り、m.mountはコンポーネントを受け取ります。

// m.renderのためにコンポーネントをm()でラップする
m.render(document.body, m(MyComponent))

// m.mountはコンポーネントをそのまま使用できる
m.mount(document.body, MyComponent)

Mithrilは1アニメーションフレーム(通常16ミリ秒)以内に再度再描画が行われると、自動再描画をスキップします。onresizeonscrollなどの高頻度イベントを使って再描画を指示した場合にも、Mithrilは再描画の頻度を調整し、ラグを避けます。


License: MIT. © Leo Horie.