自動重繪系統
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
觸發時,其他區塊已經完成重繪。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.render
而不是 m.mount
。
請記住,m.render
期望一個 vnode 樹,而 m.mount
期望一個元件:
// 將元件包裝在 m() 呼叫中以用於 m.render
m.render(document.body, m(MyComponent));
// 不要為 m.mount 包裝元件
m.mount(document.body, MyComponent);
如果請求重繪的頻率超過一個動畫幀 (通常約 16 毫秒),Mithril.js 也可能會避免自動重繪。舉例來說,當您使用像是 onresize
或 onscroll
這類快速觸發的事件時,Mithril.js 會自動限制重繪的次數,以避免畫面延遲。