使用循环中调用的构造函数添加事件侦听器的问题

时间:2019-07-20 07:04:00

标签: javascript html

我想在 div'view'中创建100个元素,所有元素都与 div'personViewPane-template'中定义的UI模板相同。

我在js中也有100个 class'personViewPane'对象的数组,每个对象都绑定到其先前创建的相应DOM元素,以便我可以使用相应的DOM操作对象的功能。

HTML

<head>
<style>
*{border:0;margin:0;padding:0;box-sizing:border-box;font-family:Calibri;}
.container{display:inline-block;height:170px;padding:5px;background:rgb(0,150,200);margin:5px;}
.image{width:140px;height:140px;background-size:cover;}
.text{width:140px;height:20px;text-align:center;color:white;}
</style>
</head>


<body>

<div id="view"></div>

<!--//////////////templates//////////////-->
<div style="display:none;">

<div id="personViewPane-template" >
<div id="{{componentID}}" class="container">
    <div class="image" style="background:red;"></div>
    <div class="text"></div>
</div>
</div>

</div>
<!--//////////end of templates////////////-->

</body>

这是流程

内部循环

  • 通过调用构造函数 personViewPane(id,id_of_parent_Element)
  • 创建personViewPane对象

内部构造函数

  • 通过调用 loadTemplate()
  • 将html模板加载到对象中
  • 在模板中,通过调用 render()
  • 用动态创建的ID替换字段“ {{componentID}}”
  • 将模板添加到 div'视图'
  • 通过调用 createHandle()获取新添加的DOM元素,并将其存储在变量 handle
  • 通过调用 addListeners()
  • 将事件侦听器添加到DOM元素
  • 通过调用 validateUI()
  • 将变量添加到DOM元素中

问题在于addEventListener仅适用于最后创建的元素。我发现了类似的问题,例如this one,其中addEventListener在循环内被调用,但我希望从构造函数中调用它。

有什么想法吗?

JavaScript

<script>

class pane
{
componentID="";
template="";
handle;

constructor()   
{this.componentID="";}

loadTemplate(x) 
{this.template=x;}

render()    
{this.template = this.template.replace('{{componentID}}',this.componentID);return this.template;}

createHandle()  
{this.handle=document.getElementById(this.componentID);}

getHandle() 
{return this.handle;}

}//end of class pane




class personViewPane extends pane
{
name="";

constructor(id, container)
{
    super();
    this.componentID=personViewPane.name+id;
    this.name = "user"+id;
    this.loadTemplate(document.getElementById('personViewPane-template').innerHTML);    
    document.getElementById(container).innerHTML+=this.render();
    this.createHandle();
    this.addListeners();
    this.validateUI();
}

validateUI(){this.getHandle().getElementsByClassName('text')[0].innerHTML= this.name;}

addListeners()
{
    var parent = this;
    var showName = function(){alert(parent.componentID);}
    this.getHandle().addEventListener( "click", showName);
}


}//end of class personViewPane



var p =[];

for(let i=0; i<100; i++)
{
p[i] = new personViewPane(i,'view');  // create objects
}

</script>

1 个答案:

答案 0 :(得分:2)

此代码的问题是

document.getElementById(container).innerHTML+=this.render();

实际上是用模板替换了具有点击侦听器的旧模板。我使用了appendChild而不是innerHTML,它运行良好。作为附带效果,我更改了loadTemplate,render和构造函数。

loadTemplate(x) {
  this.template = x.cloneNode(true);
}

render() {
  this.template.setAttribute('id', this.componentID);
  return this.template;
}

constructor(id, container) {
  super();
  this.componentID = personViewPane.name + id;
  this.name = "user" + id;
  this.loadTemplate(
    document.getElementById("personViewPane-template").firstElementChild
  );
  document.getElementById(container).appendChild(this.render());
  this.createHandle();
  this.addListeners();
  this.validateUI();
}

我用代码笔尝试了同样的方法。 Here是指向它的链接。