自动重绘系统
Mithril.js 实现了一个用于快速渲染的虚拟 DOM 差异比较系统。此外,它还提供了多种机制来精细地控制应用程序的渲染。
在通常的使用方式下,Mithril.js 采用自动重绘系统,该系统会在数据层发生更改时自动更新 DOM。当您调用 m.mount
或 m.route
时,自动重绘系统会被启用(但如果您的应用程序仅通过 m.render
调用来引导,则它会保持禁用状态)。
自动重绘系统仅在特定函数执行完毕后,才会在后台触发重新渲染。
事件处理程序之后
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
的 resolve
回调以及第三方库事件处理程序(如 Socket.io 回调)后重绘。 在这些情况下,您需要手动调用 m.redraw()
。
Mithril.js 也不会在组件的生命周期方法执行完毕后立即重绘。 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.render` 时,需要将组件包裹在 `m()` 函数调用中
m.render(document.body, m(MyComponent));
// 使用 `m.mount` 时,不要包裹组件
m.mount(document.body, MyComponent);
如果请求的重绘频率高于一个动画帧的刷新率(通常约为 16 毫秒),Mithril.js 可能会避免自动触发重绘。 这意味着,例如,当使用像 onresize
或 onscroll
这样频繁触发的事件时,Mithril.js 会自动限制重绘的次数,以避免页面卡顿。