自動再描画システム
Mithril.js は、高速なレンダリングのために仮想 DOM 差分アルゴリズムを実装しています。さらに、アプリケーションのレンダリングを詳細に制御するための様々なメカニズムを提供します。
慣用的な使用法では、Mithril.js は、データレイヤーで変更が行われるたびに DOM を同期する自動再描画システムを採用しています。自動再描画システムは、m.mount
または m.route
を呼び出すと有効になります(ただし、アプリケーションが m.render
呼び出しのみを介して初期化される場合は無効のままです)。
自動再描画システムは、特定の処理が完了した後にバックグラウンドで再描画関数をトリガーする仕組みです。
イベントハンドラの後
Mithril.js は、Mithril.js ビューで定義されている DOM イベントハンドラの実行後に自動的に再描画を行います。
var MyComponent = {
view: function () {
return m('div', { onclick: doSomething });
},
};
function doSomething() {
// この関数が実行された後、同期的に再描画が実行されます
}
m.mount(document.body, MyComponent);
e.redraw
を false
に設定することで、特定のイベントに対する自動再描画を無効にできます。
var MyComponent = {
view: function () {
return m('div', { onclick: doSomething });
},
};
function doSomething(e) {
e.redraw = false;
// div がクリックされても再描画はトリガーされません
}
m.mount(document.body, MyComponent);
m.request 後
Mithril.js は、m.request
の完了後に自動的に再描画を行います。
m.request('/api/v1/users').then(function () {
// この関数が実行された後、再描画が実行されます
});
background
オプションを true
に設定することで、特定のリクエストに対する自動再描画を無効にできます。
m.request('/api/v1/users', { background: true }).then(function () {
// 再描画は実行されません
});
ルート変更後
Mithril.js は、m.route.set()
呼び出し後、および m.route.Link
を使用したリンクを介したルート変更後に自動的に再描画を行います。
var RoutedComponent = {
view: function () {
return [
// ルートが変更された後、非同期的に再描画が発生します
m(m.route.Link, { href: '/' }),
m('div', {
onclick: function () {
m.route.set('/');
},
}),
];
},
};
m.route(document.body, '/', {
'/': RoutedComponent,
});
Mithril.js が再描画しない場合
Mithril.js は、setTimeout
、setInterval
、requestAnimationFrame
、ネイティブの Promise
解決、およびサードパーティライブラリのイベントハンドラー(Socket.io コールバックなど)の後に再描画を行いません。これらの場合は、手動で m.redraw()
を呼び出す必要があります。
Mithril.js は、ライフサイクルメソッドの実行後には自動的に再描画を行いません。oninit
ハンドラ実行後に UI の一部が再描画されることがありますが、oninit
ハンドラが実行される時点で、UI の別の部分が既に再描画されている可能性もあります。oncreate
や onupdate
などのハンドラは、UI の再描画後に実行されます。
ライフサイクルメソッド内で明示的に再描画をトリガーする必要がある場合は、m.redraw()
を呼び出す必要があります。これにより、非同期的に再描画が実行されます。
function StableComponent() {
var height = 0;
return {
oncreate: function (vnode) {
height = vnode.dom.offsetHeight;
m.redraw();
},
view: function () {
return m('div', 'This component is ' + height + 'px tall');
},
};
}
Mithril.js は、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.js は、再描画要求の頻度が 1 アニメーションフレーム(通常約 16 ミリ秒)を超える場合、自動再描画を抑制することがあります。例えば、onresize
や onscroll
のような高頻度発生イベントを使用する場合、Mithril.js は処理の遅延を防ぐために再描画の頻度を自動的に調整します。