这是我的第一个问题因此我提前道歉可能会使用错误的网络礼节。
我正在探索使用Javascript实现双向绑定的不同解决方案,我遇到了常见错误'当在for循环中使用Closure因此总是在最后一个项目上设置计数器变量时,我在这个网站上找到了解释(和解决方案),但后来我遇到了一个不同的问题我很感激一些帮助
想象一下,我们有两组数据,其中一组包含适当的数据,即:
var data = {
data1 : 0
};
另一个描述3个元素的对象集合:
var elements = {
1 : {
target : 'main',
value : data,
element : 'div',
events : {
click : 'add'
}
},
2 : {
target : 'main',
value : data,
element : 'div',
events : {
click : 'add'
}
},
3 : {
target : 'main',
value : data,
element : 'div',
events : {
click : 'add'
}
}
}
请参阅下面的完整代码段
var data = {
data1 : 0
};
var elements = {
1 : {
target : 'main',
value : data,
element : 'div',
events : {
click : 'add'
}
},
2 : {
target : 'main',
value : data,
element : 'div',
events : {
click : 'add'
}
},
3 : {
target : 'main',
value : data,
element : 'div',
events : {
click : 'add'
}
}
}
// This is our main object, we define the properties only ...
var _elem = function (props,id){
this.id = id;
this.target = document.getElementById(props.target);
this.element = document.createElement(props.element);
this.events = props.events;
this.value = props.value;
}
// Then we add a method to render it on the page ...
_elem.prototype.render = function(){
// I added the Object Id for debugging purposes
this.element.innerHTML = this.value.data1 + ' ['+this.id+']';
this.target.appendChild(this.element);
}
// ... and another to change the underlying data and re - render it
_elem.prototype.add = function(){
// Since the data is a reference to the same data object
// We expect to change the value for all the elements
this.value.data1++;
this.render();
}
// First we looop trough the array with the element definition and
// Cast each item into a new element
for(var el in elements){
elements[el] = new _elem(elements[el],el);
}
// Then we apply the event listener (if any event description is present)
for(var el in elements){
if(!elements[el].hasOwnProperty( 'events' )){
continue;
}
// We use the anonymous function here to avoid the "common mistake"
(function() {
var obj = elements[el];
var events = obj.events;
for(var ev in events){
obj.element.addEventListener(ev,function(){ obj[events[ev]]() });
}
})();
}
// And finally we render all the elements on the page
for(var el in elements){
elements[el].render(elements[el]);
}

div {
padding: 10px;
border: solid 1px black;
margin: 5px;
display: inline-block;
}

<html>
<head>
</head>
<body>
<div id="main"></div>
</body>
</html>
&#13;
现在,如果我们点击按钮[1],它将更新自己和以下内容,从而产生以下序列:
0 [2] 0 [3] 1 [1]
我们刷新页面,这次点击按钮[2],顺序为:
0 [1] 0 [3] 1 [2]
按钮[3]而是仅更新自己
0 [1] 0 [2] 1 [3]
我在发布之前确实查找了这个主题,但我发现的所有问题都与此类似:addEventListener using for loop and passing values,其中问题是计数器变量始终保持最后一个值
在这种情况下,似乎问题恰恰相反,或者保持初始值的对象和随后的对象(如果你一直点击就会看到我的意思)
我做错了什么?
答案 0 :(得分:0)
问题似乎是你要在每个&#34;刷新&#34;上重新附加你的子元素,这会改变元素的顺序,并给出刷新多个元素的错觉。
您需要区分初始渲染和后续刷新。
我建议您从渲染功能中删除append
,然后在最终for循环中处理附加内容:
// And finally we render all the elements on the page
for(el in elements){
elements[el].render(elements[el]);
elements[el].target.append(elements[el].element);
}
请注意,有多个&#34;问题&#34;使用您的代码,包括多个位置的全局变量。而且我不相信您的架构会很好地扩展。但是,这些问题超出了你的问题的范围,你会随时学习......没有理由期望每个人都知道一切,你可能会发现你当前的解决方案适合你需要的东西它要做。
var data = {
data1 : 0
};
var elements = {
1 : {
target : 'main',
value : data,
element : 'div',
events : {
click : 'add'
}
},
2 : {
target : 'main',
value : data,
element : 'div',
events : {
click : 'add'
}
},
3 : {
target : 'main',
value : data,
element : 'div',
events : {
click : 'add'
}
}
}
// This is our main object, we define the properties only ...
var _elem = function (props,id){
this.id = id;
this.target = document.getElementById(props.target);
this.element = document.createElement(props.element);
this.events = props.events;
this.value = props.value;
}
// Then we add a method to render it on the page ...
_elem.prototype.render = function(){
// I added the Object Id for debugging purposes
this.element.innerHTML = this.value.data1 + ' ['+this.id+']';
}
// ... and another to change the underlying data and re - render it
_elem.prototype.add = function(){
// Since the data is a reference to the same data object
// We expect to change the value for all the elements
this.value.data1++;
this.render();
}
// First we looop trough the array with the element definition and
// Cast each item into a new element
for(var el in elements){
elements[el] = new _elem(elements[el],el);
}
// Then we apply the event listener (if any event description is present)
for(var el in elements){
if(!elements[el].hasOwnProperty( 'events' )){
continue;
}
// We use the anonymous function here to avoid the "common mistake"
(function() {
var obj = elements[el];
var events = obj.events;
for(ev in events){
obj.element.addEventListener(ev,function(){ obj[events[ev]]() });
}
})();
}
// And finally we render all the elements on the page
for(var el in elements){
elements[el].render(elements[el]);
elements[el].target.appendChild(elements[el].element);
}
&#13;
div {
padding: 10px;
border: solid 1px black;
margin: 5px;
display: inline-block;
}
&#13;
<html>
<head>
</head>
<body>
<div id="main"></div>
</body>
</html>
&#13;