Mithril.js中vnode绑定点击事件及传递给匿名函数的方法
Let's break down your questions clearly, with practical fixes for your code example:
1. How to bind a vnode to a click event in Mithril.js?
In Mithril, DOM event handlers receive the browser event object as their first argument by default—not the Mithril vnode. To access the vnode in your click handler, you have two simple, reliable approaches:
Leverage closure scope:
Since theviewfunction gets the vnode as a parameter, you can directly reference it inside your click handler without passing it explicitly:var Button = { view: function(vnode) { return m('div', { onclick: function() { // vnode is accessible here thanks to closure console.log("Clicked element's vnode:", vnode); } }, "Click Me"); } };Explicitly pass the vnode via an arrow function:
If you want to use a separate handler function, wrap the call in an arrow function to pass the vnode through. Just make sure you don't name the arrow function's parametervnode(that would shadow the outer vnode variable):function handleClick(vnode) { // Work with the Mithril vnode here console.log("Handling click for:", vnode.attrs); } var Button = { view: function(vnode) { return m('div', { onclick: () => handleClick(vnode) }, "Click Me"); } };
2. Fixing your Webpack project code to pass the vnode correctly
Looking at your original code, there's a common shadowing issue that's preventing you from getting the right vnode:
// Your original code (has a bug) var Button = { view:function(vnode){ return m('div',{onclick:(vnode)=> setSort(vnode)}) } } function setSort(vnode){ .... do somthing with vnode .... }
The problem is that the arrow function's parameter is named vnode, which overwrites (shadows) the vnode variable from the view function. Inside that arrow function, vnode is actually the browser click event—not the Mithril vnode you need!
Here's the fixed version:
Option 1: Pass the vnode without shadowing
function setSort(vnode) { // Now this vnode is the actual Mithril vnode from the view console.log("Using vnode to update state:", vnode.state); // Add your sorting logic here } var Button = { view: function(vnode) { // The arrow function doesn't define its own vnode parameter, so it uses the outer one return m('div', { onclick: () => setSort(vnode) }, "Sort"); } };
Option 2: Access both the event and vnode
If you need the browser event object too, rename the arrow function's parameter to avoid shadowing:
function setSort(event, vnode) { console.log("Click event details:", event.target); console.log("Mithril vnode data:", vnode.attrs.sortKey); // Your sorting logic here } var Button = { view: function(vnode) { return m('div', { onclick: (e) => setSort(e, vnode) }, "Sort"); } };
This works exactly the same in Webpack projects—Webpack only bundles your code, so Mithril's core behavior with vnodes and closures stays unchanged.
内容的提问来源于stack exchange,提问作者Tal Yaron

