Mithril中使用m.component()时如何遍历VDOM?
How to traverse VDOM when using m.component() in Mithril?
我是 Mithril 的新手,但对它执行良好编码模式和关注点分离的方式感到非常满意。参考这个我开始编码,大量使用 m.component().
后来我阅读了 Mithril-Article "When CSS lets you down" (http://lhorie.github.io/mithril-blog/when-css-lets-you-down.html),它解释了如何编写 Transformer-Functions 来遍历和操作虚拟 DOM-Tree。编写多种横切关注点的绝妙概念。
但是当我尝试将此模式与包含组件的 VDOM 一起使用时,它不起作用,因为 m.component 返回的是组件而不是 VDOM-Object .检测组件没有帮助,因为此时尚未构建嵌入式视图。
现在我问自己,如何处理这个问题,或者我是否误解了根本错误的东西...
这里有几行代码显示了问题:
...
someComponent.view = function() {
return m('html', [
m('body', [
m('div', [
m.component(anotherComponent)
])
])
};
...
// and now the traversal function from the mithril side
var highlightNegatives = function (root, parent) {
if (!root) return root;
else if (root instanceof Array) {
for (var i = 0; i < root.length; i++) {
highlightNegatives(root[i], parent);
}
} else if (root.children) {
highlightNegatives(root.children, root);
} else if (typeof child == "string" && child.indexOf("($") === 0) {
parent.attrs.class = "text-danger";
}
return root;
};
highlightNegatives(someComponent.view()); // will not find the relevant elements in "anotherComponent"
其他人如何处理该问题?
组件是在博客 post 写完后添加的。
您需要先将组件转换为 vDOM 对象,然后才能将其包含在视图中。请注意,我已经这样做了 2 次,一次是在我们遍历 vDOM 树时在 highlightNegatives() 函数中捕获组件,一次是在我们在视图中调用它时在函数参数中。
您可以只包含组件标识符而不调用 m.component(),除非您要向组件发送属性或其他选项:
myComponent
vs.
m.component( myComponent, {extraStuff: [1,2,3]}, otherStuff )
调用 highlightNegatives() 时需要考虑这一点。
无需在模板中包含 html 和 body。浏览器会为您完成此操作(或者您当然可以将它们包含在 index.html 中)
下面是代码的一个工作示例:
http://jsbin.com/poqemi/3/edit?js,output
var data = ['.00', '(.00)', '.00', '(.00)', '(.00)']
var App = {
view: function(ctrl, attrs) {
return m("div.app", [
m('h1', "My App"),
someComponent
])
}
}
var anotherComponent = {
controller: function (){
this.data = data
},
view: function (ctrl){
return m('div.anotherComponent', [
m('h3', 'anotherComponent'),
ctrl.data.map( function(d) {
return m('li', d)
})
])
}
}
var someComponent = {}
someComponent.controller = function (){ }
someComponent.view = function (ctrl) {
return m('div.someComponent', [
m('h2', 'someComponent'),
highlightNegatives(anotherComponent.view( new anotherComponent.controller() ))
])
};
// and now the traversal function from the mithril side
var highlightNegatives = function (root, parent) {
if (!root) return root;
else if (root instanceof Array) {
for (var i = 0; i < root.length; i++) {
// when you encounter a component, convert to VDOM object
if (root[i].view) {
highlightNegatives(root[i].view( new root[i].controller() ))
}else{
highlightNegatives(root[i], parent);
}
}
} else if (root.children) {
highlightNegatives(root.children, root);
} else if (typeof root == "string" && root.indexOf("($") === 0) {
parent.attrs.class = "text-danger";
}
return root;
};
m.mount(document.body, App)
//Calling this function after the App is mounted does nothing.
//It returns a vDOM object that must be injected into the someComponent.view
//highlightNegatives(someComponent.view()); // will not find the relevant elements in "anotherComponent"
我是 Mithril 的新手,但对它执行良好编码模式和关注点分离的方式感到非常满意。参考这个我开始编码,大量使用 m.component().
后来我阅读了 Mithril-Article "When CSS lets you down" (http://lhorie.github.io/mithril-blog/when-css-lets-you-down.html),它解释了如何编写 Transformer-Functions 来遍历和操作虚拟 DOM-Tree。编写多种横切关注点的绝妙概念。
但是当我尝试将此模式与包含组件的 VDOM 一起使用时,它不起作用,因为 m.component 返回的是组件而不是 VDOM-Object .检测组件没有帮助,因为此时尚未构建嵌入式视图。
现在我问自己,如何处理这个问题,或者我是否误解了根本错误的东西...
这里有几行代码显示了问题:
...
someComponent.view = function() {
return m('html', [
m('body', [
m('div', [
m.component(anotherComponent)
])
])
};
...
// and now the traversal function from the mithril side
var highlightNegatives = function (root, parent) {
if (!root) return root;
else if (root instanceof Array) {
for (var i = 0; i < root.length; i++) {
highlightNegatives(root[i], parent);
}
} else if (root.children) {
highlightNegatives(root.children, root);
} else if (typeof child == "string" && child.indexOf("($") === 0) {
parent.attrs.class = "text-danger";
}
return root;
};
highlightNegatives(someComponent.view()); // will not find the relevant elements in "anotherComponent"
其他人如何处理该问题?
组件是在博客 post 写完后添加的。
您需要先将组件转换为 vDOM 对象,然后才能将其包含在视图中。请注意,我已经这样做了 2 次,一次是在我们遍历 vDOM 树时在 highlightNegatives() 函数中捕获组件,一次是在我们在视图中调用它时在函数参数中。
您可以只包含组件标识符而不调用 m.component(),除非您要向组件发送属性或其他选项:
myComponent
vs.
m.component( myComponent, {extraStuff: [1,2,3]}, otherStuff )
调用 highlightNegatives() 时需要考虑这一点。
无需在模板中包含 html 和 body。浏览器会为您完成此操作(或者您当然可以将它们包含在 index.html 中)
下面是代码的一个工作示例: http://jsbin.com/poqemi/3/edit?js,output
var data = ['.00', '(.00)', '.00', '(.00)', '(.00)']
var App = {
view: function(ctrl, attrs) {
return m("div.app", [
m('h1', "My App"),
someComponent
])
}
}
var anotherComponent = {
controller: function (){
this.data = data
},
view: function (ctrl){
return m('div.anotherComponent', [
m('h3', 'anotherComponent'),
ctrl.data.map( function(d) {
return m('li', d)
})
])
}
}
var someComponent = {}
someComponent.controller = function (){ }
someComponent.view = function (ctrl) {
return m('div.someComponent', [
m('h2', 'someComponent'),
highlightNegatives(anotherComponent.view( new anotherComponent.controller() ))
])
};
// and now the traversal function from the mithril side
var highlightNegatives = function (root, parent) {
if (!root) return root;
else if (root instanceof Array) {
for (var i = 0; i < root.length; i++) {
// when you encounter a component, convert to VDOM object
if (root[i].view) {
highlightNegatives(root[i].view( new root[i].controller() ))
}else{
highlightNegatives(root[i], parent);
}
}
} else if (root.children) {
highlightNegatives(root.children, root);
} else if (typeof root == "string" && root.indexOf("($") === 0) {
parent.attrs.class = "text-danger";
}
return root;
};
m.mount(document.body, App)
//Calling this function after the App is mounted does nothing.
//It returns a vDOM object that must be injected into the someComponent.view
//highlightNegatives(someComponent.view()); // will not find the relevant elements in "anotherComponent"