Javascript 为什么将IIFEs与Mithril.js一起使用时,组件的所有实例的最新实例中的属性会覆盖状态?
我正在试用Mithril.js,并制作了三个小组件Javascript 为什么将IIFEs与Mithril.js一起使用时,组件的所有实例的最新实例中的属性会覆盖状态?,javascript,iife,mithril.js,Javascript,Iife,Mithril.js,我正在试用Mithril.js,并制作了三个小组件 let Map = (function() { let Map = {}; let parent; Map.oninit = function(vnode) { parent = vnode.attrs.parent; } Map.view = function(vnode) { return m("p", parent) } Map.onupdate
let Map = (function() {
let Map = {};
let parent;
Map.oninit = function(vnode) {
parent = vnode.attrs.parent;
}
Map.view = function(vnode) {
return m("p", parent)
}
Map.onupdate = function(vnode) {
console.log(parent);
}
return Map;
})();
let Popup = (function() {
let Popup = {};
Popup.view = function(vnode) {
return m(Map, {parent: "Popup"});
}
return Popup;
})();
let Dashboard = (function() {
let Dashboard = {};
Dashboard.view = function(vnode) {
return m("div", [
m(Map, {parent: "Dashboard"}),
m(Popup),
m("button",
{
onclick: function(e) {
//Click event that doesn't do anything. Just added to trigger Mithril redraw
}
}, "Redraw")
]);
}
return Dashboard;
})();
m.mount(document.body, Dashboard);
主要的外部组件是仪表板,应该显示地图组件和弹出组件。弹出组件显示了Map的另一个实例。当显示映射组件时,我发送一个字符串,将父组件的名称作为属性,并将一个局部变量设置为该属性。Map组件只返回一个包含此变量的简单段落,以显示父组件的名称。仪表板显示两个段落,其中包含父组件的名称和一个按钮,以便单击时Mithril将重新绘制
初始化时,它按预期工作,并显示包含“Dashboard”的段落、包含“Popup”的段落和按钮。问题是,当我点击按钮更新DOM时,两个段落现在都显示“Popup”。因此,出于某种原因,这两个实例都使用最新的值。我可以通过将映射组件重写为非IIFE来修复此问题,如下所示:
function Map() {
let parent;
return {
oninit : function(vnode) {
parent = vnode.attrs.parent;
},
view : function(vnode) {
return m("p", parent);
},
onupdate: function(vnode) {
console.log(parent);
}
}
}
为什么作为一个生命的版本不能像我预期的那样工作,我如何在保持它作为一个生命的同时使它工作?就像@Bergi所说的,可能更容易放弃这个生命。这里我转换了您必须使用的闭包样式组件。您可以使用POJO作为组件,但我不建议使用它,因为状态令人困惑 当您立即调用该函数时,您将返回一个Map对象。该对象在弹出窗口中使用,因此您可以在所有代码中使用相同的对象。我相信有一个大脑巨大的人可以通过所有的调用来确定确切的位置,要么值只设置了一次,要么值发生了冲突,但无论如何,你不能让父对象设置为同一地图对象上的两个不同的对象。这是令人惊讶的第一次工作,但正如你所看到的,它是不可靠的 我删除了IIFE,并用Component后缀重命名了组件,以使代码更加清晰
let MapComponent = function() {
let Map = {};
let parent;
Map.oninit = function(vnode) {
parent = vnode.attrs.parent;
}
Map.view = function(vnode) {
return m("p", parent)
}
Map.onupdate = function(vnode) {
console.log(parent);
}
return Map;
};
let PopupComponent = function() {
let Popup = {};
Popup.view = function(vnode) {
return m(MapComponent, {parent: "Popup"});
}
return Popup;
};
let Dashboard = (function() {
let Dashboard = {};
Dashboard.view = function(vnode) {
return m("div", [
m(MapComponent, {parent: "Dashboard"}),
m(PopupComponent),
m("button", {
onclick: function(e) {
//Click event that doesn't do anything. Just added to trigger Mithril redraw
}
}, "Redraw")
]);
}
return Dashboard;
})();
m.mount(document.body, Dashboard);
您没有包含实例的组件。代码中只有一个
Map
模块,它有一个parent
变量。当你想创建多个独立的对象时,为什么要尝试使用iLife?@Bergi似乎对它的工作原理没有很好的理解。我想使用父变量更改贴图的外观。例如,如果父对象是仪表板,我希望贴图具有给定的大小。因此,一个映射可能具有给定的大小和所有功能,而另一个映射可能更小,功能更有限,因为父组件是其他组件,如弹出窗口。组件应该这样使用,还是我误解了它们应该如何使用?