【问题标题】:How to change contents of a virtual dom element in Mithril?如何更改 Mithril 中虚拟 dom 元素的内容?
【发布时间】:2019-09-15 05:43:18
【问题描述】:
如何使用 Mithril 访问虚拟 dom 元素以更改其内容?我是 Mithril 的新手,仍在努力解决问题。例如,我想访问 ID 为“three”的第三个 div,并将其内容更改为“Blue Jays”,而不触及任何其他 div。
谢谢。
<div id='main'>
<div id='one'>Yankees</div><br>
<div id='two'>Red Sox</div><br>
<div id='three'>Orioles</div>
</div>
【问题讨论】:
-
您可以使用 vnode 的 dom 属性访问 dom。您只需将此 dom 分配给 vnode 对象。比如 vnode.state.el = { ....
}
标签:
mithril.js
virtual-dom
【解决方案1】:
在 mithril 中,就像在 react/vue/angular 中一样,您不会直接对实际的 DOM 进行操作。相反,您可以定义您想要的结果,例如,要渲染您发布的 DOM 树,您可以执行以下操作:
var my_view = {
view: vnode => m('div#main', [
m('div#one', 'Yankees'),
m('div#two', 'Red Sox'),
m('div#three', 'Orioles')
])
}
m.mount(root, my_view)
<script src="https://cdnjs.cloudflare.com/ajax/libs/mithril/2.0.4/mithril.js"></script>
<div id="root"></div>
数组中的m(...) 函数有一个字符串作为第二个参数,这使得输出是静态的,但我们可以将其更改为变量:
var my_view = {
oninit: vnode => vnode.state.fave_team = 'Orioles',
view: vnode => m('div#main', [
m('div#one', 'Yankees'),
m('div#two', 'Red Sox'),
m('div#three', vnode.state.fave_team)
])
}
m.mount(root, my_view)
<script src="https://cdnjs.cloudflare.com/ajax/libs/mithril/2.0.4/mithril.js"></script>
<div id="root">
</div>
在这种情况下,我使用了 vnode 参数的 state 属性,但您也可以使用第三方状态管理器,如 Flux 或任何其他。
现在我们把它作为一个变量,它会在每次调用m.redraw()时显示当前值,大多数时候我们不必自己做这个调用,例如:
var my_view = {
oninit: vnode => {
vnode.state.fave_team = 'Orioles'
},
view: vnode => m('div#main', [
m('div#one', 'Yankees'),
m('div#two', 'Red Sox'),
m('div#three', vnode.state.fave_team),
m('button', { onclick: () => vnode.state.fave_team = 'Dodgers' }, 'Change')
])
}
m.mount(root, my_view)
<script src="https://cdnjs.cloudflare.com/ajax/libs/mithril/2.0.4/mithril.js"></script>
<div id="root"></div>
就是这样,您将 DOM 元素中的任何动态内容设置为对象中的变量/属性。
秘银的优点之一是它不会强迫你以一种特定的方式做事,所以如果你真的想在实际的 DOM 节点上工作,there are lifecycle events 你可以附加到任何虚拟节点(“vnode ")
【解决方案2】:
您可以使用 oncreate() 的 Mithril Lifecycle 事件轻松捕获 HTMLElement(即 HTMLInputElement)。这是我的代码(在 TypeScript 中)中的一个实际示例,我需要在创建画布元素后连接一些事件侦听器,并且它的底层 DOM 在“原始”HTML 级别可供我使用。一旦你掌握了dom,我就会直接操纵那个元素。很多人认为为什么不使用oninit(),但是oninit()是在dom生成之前,所以你不会在那个阶段取回元素。
现在,如果您这样做,您可能会发布另一个问题 - “为什么浏览器视图没有更新?”那是因为您必须在事件处理程序中手动执行 m.redraw()。否则 Mithril 将不知道何时计算视图差异。
const canvas = m(`.row[tabIndex=${my.tabIndex}]`, {
oncreate: (element: VnodeDOM<any, any>) => {
const dom = element.dom;
dom.addEventListener("wheel", my.eventWheel, false);
dom.addEventListener("keydown", my.eventKeyDown, false);
}
},