Heim > Web-Frontend > js-Tutorial > Hauptteil

So fügen Sie Elemente dynamisch in JS hinzu

亚连
Freigeben: 2018-06-22 13:55:29
Original
2286 Leute haben es durchsucht

Dieser Artikel stellt Ihnen hauptsächlich die relevanten Informationen über die wiederholte Ausführung von Programmen vor, die durch dynamisches Hinzufügen von Elementen und Bindungsereignissen in JS verursacht werden. Der Artikel führt sie ausführlich anhand von Beispielcode ein, der für das Studium oder die Arbeit eines jeden einen gewissen Referenzwert hat . Freunde, die es brauchen, können unten vorbeischauen.

Vorwort

In diesem Artikel geht es vor allem um den Fehler, der vor einiger Zeit aufgetreten ist und bei dem viele interaktive Methoden von jquery gebunden werden Leute haben über die wiederholte Ausführung von Programmen geschrieben, die durch Code wie $('#point').on('click','.read-more',function () {}) verursacht werden, und auch die Verwendung der Off-Methode zum Aufheben der Bindung erwähnt, aber sie haben es versäumt, auf den Kern des Problems hinzuweisen, und fast alle haben die tatsächliche Natur ignoriert des Problems wird durch die Ereignisdelegierung verursacht.

Ohne weitere Umschweife, hier sind die Codes, die ich jeden Tag sehe:

Der erste Typ:

 $(document).on('click', function (e) {
 consol.log('jquery事件绑定')
 });
Nach dem Login kopieren

Zweiter Typ:

 document.addEventListener('click',function (e) {
 consol.log('原生事件绑定')  
 });
Nach dem Login kopieren

Dritter Typ:

 var id = setInterval(function () {
 console.log('定时器循环事件绑定')
 },1000);
Nach dem Login kopieren

Ich glaube, viele Allianzmitglieder schreiben jeden Tag den obigen Code, so gut Sie können Sehen Sie, scheinbar einfache Ereignisbindung kann uns oft unerwartete Ergebnisse bringen, insbesondere in einer Zeit, in der SPA und AJAX-Seitenteilaktualisierungen so beliebt sind.

Was ist also Ereignisbindung und was verursacht die wiederholte Ausführung von Programmen? Wenn es darum geht, dieses Problem zu klären, scheint es nicht so einfach zu sein. Lassen Sie uns einen Testcode verwenden, um es zu veranschaulichen. Sie können es lokal kopieren und selbst ausprobieren:

<!DOCTYPE html>
<html>
<head>
 <meta charset="UTF-8">
 <title>Title</title>
</head>
<body>
<button class="add_but">点击</button>
<p id="point">fdfsdf
</p>
<script src="https://cdn.bootcss.com/jquery/1.8.3/jquery.js"></script> 
<script>
 var count=1;
 var example = {
 getData:function () {
  var data ={
  content:&#39;df&#39;+count++,
  href:&#39;&#39;
  };
  this.renderData(data);
 },
 renderData:function (data) {
  document.getElementById(&#39;point&#39;).innerHTML=&#39;<p>this is a &#39;+data.content+&#39;点此<a class="read-more" href="javasript:;" rel="external nofollow" rel="external nofollow" >查看更多</a></p>&#39;;
  $(&#39;#point&#39;).on(&#39;click&#39;,&#39;.read-more&#39;,function () {
  alert(&#39;事故发生点&#39;);
 })
/*  setInterval(function () {
  console.log(&#39;fdfdfg&#39;);
  },2000);*/
  /*用冒泡来绑定事件,类似于Jquery的on绑定事件*/
 /* document.querySelector(&#39;body&#39;).addEventListener(&#39;click&#39;,function (e) {
  if(e.target.classList.contains(&#39;read-more&#39;)){
   alert(&#39;事故发生点&#39;);
  }
  })*/

 }
 } ;
 document.querySelector(&#39;.add_but&#39;).addEventListener(&#39;click&#39;,function (e) {
 example.getData();
 e.stopImmediatePropagation();
 });
</script>
</body>
</html>
Nach dem Login kopieren

Das Obige ist ein Testcode, den ich geschrieben habe, um dieses Problem zu klären. Sie können es kopieren und ausprobieren. Wenn wir auf die Schaltfläche auf der Seite klicken, wird die Funktion example.getData() aufgerufen. Nach erfolgreicher Ajax-Erfassung wird der Inhalt der Elementklasse mit dem Namen point auf der Seite lokal aktualisiert und das read-more Ein Tag darin Der Inhalt wird geladen, und der gewünschte Effekt wird angezeigt. Wenn das Element zum ersten Mal geladen wird, wird der „Unfallpunkt“ einmal angezeigt Stellen Sie fest, dass es zweimal auftaucht. Beim dritten Mal werden Sie feststellen, dass es dreimal springt, und so weiter. . . .

OMG, was ist mit diesem Programm los? Ich weiß ganz genau, dass die zuvor gebundenen Elemente gelöscht werden. Nun, das oben Gesagte ist mein erster An Ausruf, wenn man auf diese Situation stößt.

Schließlich fragte ich den Master um mich herum und mir wurde plötzlich klar, dass die Bindung immer da war und diese Bindung an einem Ort namens Ereigniswarteschlange gespeichert war. Er befand sich nicht im Hauptthread der Schleifenausführung , und zeichnete ein Bild, das stillschweigendes Verständnis erfordert, um verstanden zu werden, also warf ich widerwillig einen Blick darauf.

Ereigniswarteschlange

Stellen Sie die Wahrheit wieder her

Tatsächlich der obige Code ist für den Code speziell zum Testen geschrieben, die anderen beiden Klickereignisse werden nicht auf normale Weise geschrieben:

 // jquery 事件直接绑定的写法;
 $(&#39;#point .read-more&#39;).on(&#39;click&#39;,function () {
  alert(&#39;事故发生点&#39;);
 })
 // 原生JS 事件直接绑定的写法;
 document.querySelector(&#39;.read-more&#39;).addEventListener(&#39;click&#39;,function (e) {
  alert(&#39;事故发生点&#39;);
 })
Nach dem Login kopieren

Sehen Sie den Unterschied? Tatsache ist, dass keine Notwendigkeit besteht, die Ereignisdelegation aufzublasen, sondern Ereignisse direkt an die hinzugefügten Elemente zu binden. Daher sind Dom-Ereignisse dynamisch an dieses Element gebunden. Nachdem das Element gelöscht wurde, wird das entsprechende daran gebundene Ereignis tatsächlich aus der Ereignisbindungswarteschlange gelöscht Obiger Testcode, der den Eindruck erweckt, dass sich die gebundenen Ereignisse nach dem Entfernen des Elements immer noch im Speicher befinden. Aber bitte denken Sie daran, der oben getestete Code vermittelt diese Illusion, weil wir Ereignisse nicht an dynamisch hinzugefügte Elemente binden, sondern nur die Ereignisdelegation verwenden, tatsächlich ist das Ereignis an das # gebunden. Das Punktelement, das immer vorhanden ist, wird verwendet, um dem Programm mitzuteilen, dass wir auf das dynamisch hinzugefügte Linkelement geklickt haben. Im Test wurde bewusst natives js verwendet, um die Ereignisdelegation zu reproduzieren. Das Prinzip von jquery beim Binden von Ereignissen ist grundsätzlich dasselbe.

document.querySelector(&#39;body&#39;).addEventListener(&#39;click&#39;,function (e) {
 if(e.target.classList.contains(&#39;read-more&#39;)){
  alert(&#39;事故发生点&#39;);
 }
})
Nach dem Login kopieren

Diese Methoden zur Fehlerbeseitigung

Timer

Das ist der häufigste Fehler Der Fehler ist natürlich am einfachsten zu lösen, da beim Einstellen des Timers ein Wert im Timer in der Ereigniswarteschlange zurückgegeben wird, ähnlich wie bei 9527. Der Schritt besteht darin, eine globale Variable auf „Behalten“ zu setzen Rückgabewert id. Jedes Mal, wenn Sie einen Timer einstellen, löschen Sie zuerst den Timer, der von id eingestellt wurde Wie bereits erwähnt, besteht der direkteste Weg nicht darin, die Ereignisdelegation zu verwenden, sondern die direkte Bindung zu verwenden. Wenn Sie die Ereignisdelegation wirklich zum Binden von Ereignissen verwenden möchten, lösen Sie die Bindung. Die Unbind-Funktion wird in JQuery zum Aufheben der Bindung von Ereignissen bereitgestellt. Nach JQuery 1.8 wird diese Methode jedoch nicht mehr empfohlen und die Off-Methode wird empfohlen. Wenn Sie beispielsweise die obige On-Event-Delegationsmethode entbinden möchten, können Sie die Anweisung

verwenden.

有缺陷的解决方案,添加flag

很好理解,第一次绑定后,flag置位,下一次在执行这个绑定时,程序就知道在这个节点上已经有了绑定,无需再添加,具体操作就是:

 var flag = false;
 var example = {
 getData: function () {
  var data = {
  content: &#39;df&#39; + count++,
  href: &#39;&#39;
  };
  this.renderData(data);
 },
 renderData: function (data) {
  document.getElementById(&#39;point&#39;).innerHTML = &#39;<p>this is a &#39; + data.content + &#39;点此<a class="read-more" href="javasript:;" rel="external nofollow" rel="external nofollow" >查看更多</a></p>&#39;;
  !flag && $(&#39;#point&#39;).on(&#39;click&#39;, &#39;.read-more&#39;, function () {
  alert(&#39;事故发生点&#39;+data.content);
  });
  flag = true;
 }
 };
Nach dem Login kopieren

从逻辑上,看起来没有问题,但仔细观察,发现这是有问题的。当我们第二次,第三次刷新时,弹出框的内容还是和第一次模拟刷新后点击后弹出的内容一致,还是'事故发生点df1',而非和内容一样递增,为什么呢,感觉事件队列里面的回调函数被单独保存起来了,data被深拷贝了,而不再是一个引用。确实有点难理解,我也不知道到底是为什么,如果哪位能说清楚,还请一定告知。

结个尾写在最后,其实平常写一些程序时,事件绑定,造成程序重复执行这些情况很少发生,其通常会出现在我们写插件的时候,插件需要适应多种调用环境,所以在插件内部做到防止事件重复绑定的情况非常重要。

上面是我整理给大家的,希望今后会对大家有帮助。

相关文章:

使用node.js如何创建子进程(详细教程)

使用ES6如何实现单例模式

如何把Angular项目部署到nginx上

在vue中使用v-model如何实现父子组件通信

在react中有关组件通信有哪些方法?

Das obige ist der detaillierte Inhalt vonSo fügen Sie Elemente dynamisch in JS hinzu. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
js
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!