mount(root, component)
描述
激活组件,使其能够在用户事件触发时自动重绘。
var state = {
count: 0,
inc: function () {
state.count++;
},
};
var Counter = {
view: function () {
return m('div', { onclick: state.inc }, state.count);
},
};
m.mount(document.body, Counter);
要在挂载组件时传递参数,可以使用以下方式:
m.mount(element, {
view: function () {
return m(Component, attrs);
},
});
签名
m.mount(element, Component)
参数名 | 类型 | 是否必需 | 描述 |
---|---|---|---|
element | Element | 是 | 一个 DOM 元素,它将作为子树的父节点。 |
Component | Component|null | 是 | 要渲染的组件。null 会卸载该树并清理内部状态。 |
返回 | 无。 |
工作原理
m.mount(element, Component)
调用时,会将组件渲染到指定的 DOM 元素中,并将 (element, Component)
这一对元素订阅到重绘子系统。当触发手动或自动重绘时,该组件树会被重新渲染。
重绘时,新的 vDOM 树会与旧的 vDOM 树进行比较(即进行“差异比较”),并且仅在需要反映更改的地方修改现有的 DOM 树。未发生改变的 DOM 节点不会被修改。
替换组件
如果 element
为当前挂载点,并且运行 mount(element, OtherComponent)
,则会将先前挂载的组件替换为 OtherComponent
组件。
卸载
在已经挂载了组件的元素上使用 m.mount(element, null)
会卸载该组件并清理 Mithril.js 的内部状态。当手动从 DOM 中删除 root
节点时,这有助于防止内存泄漏。
无头挂载
可以通过无头挂载来实现某些特殊需求,只需使用一个未添加到活动 DOM 树的元素调用 m.mount
,并将所有逻辑放入要挂载的组件中。组件中仍然需要一个 view
函数,但它不必返回任何有意义的内容,可以返回 null
等无效值。
var elem = document.createElement('div');
// 订阅
m.mount(elem, {
oncreate: function () {
// 添加后
},
onupdate: function () {
// 每次重绘时
},
onremove: function () {
// 清理你需要清理的任何东西
},
// 必要的样板代码
view: function () {},
});
// 取消订阅
m.mount(elem, null);
无需担心与其他挂载根的冲突。Mithril.js 支持多个根,它们不会互相干扰。您甚至可以在与另一个框架集成时在组件中执行上述操作,这不会有问题。
性能注意事项
每次重绘都生成 vnode 树可能看起来会浪费资源,但实际上,与直接读取和修改 DOM 相比,创建和比较 JavaScript 数据结构的开销要小得多。
操作 DOM 可能会非常消耗资源。交替进行读取和写入操作可能会导致浏览器频繁重绘,从而对性能产生负面影响。而比较虚拟 DOM 树则可以将多次写入操作合并为一次重绘。此外,不同浏览器对 DOM 操作的性能优化各不相同,因此很难针对所有浏览器进行学习和优化。例如,在某些实现中,读取 childNodes.length
的复杂度为 O(n);在某些实现中,读取 parentNode
会导致重绘等。
相比之下,遍历 JavaScript 数据结构具有更可预测且合理的性能表现。此外,vnode 树的实现方式使现代 JavaScript 引擎能够应用激进的优化,例如隐藏类,以获得更好的性能。
与 m.render 的区别
通过 m.mount
渲染的组件会自动重绘,以响应视图事件、m.redraw()
调用或 m.request()
调用,而通过 m.render()
渲染的 Vnode 则不会。
m.mount()
适用于那些需要将 Mithril.js 组件集成到现有代码库中的应用程序开发者,这些代码库的路由可能由其他库或框架处理,但仍然希望利用 Mithril.js 的自动重绘机制。
m.render()
适用于希望手动控制渲染过程的库作者,例如,当需要与第三方路由器或数据层库(如 Redux)集成时。