Tıklama etkinliğini bir innerHTML içine nasıl alabilirim?


12

Dinamik olarak oluşturulmuş bu düzen var:

for (let i = 1; i < 10; i++) {
  document.querySelector('.card-body').innerHTML += `<div class="row" id="img_div">
        <div class="col-12 col-sm-12 col-md-2 text-center">
          <img src="http://placehold.it/120x80" alt="prewiew" width="120" height="80">
        </div>
        <div id="text_div" class="col-12 text-sm-center col-sm-12 text-md-left col-md-6">
        <h4 class="name"><a href="#" id="title` + i + `">Name</a></h4>
          <h4>
            <small>state</small>
          </h4>
          <h4>
            <small>city</small>
          </h4>
          <h4>
            <small>zip</small>
          </h4>
        </div>
        <div class="col-12 col-sm-12 text-sm-center col-md-4 text-md-right row">
        </div>
      </div>
     `
  document.getElementById("title" + i).addEventListener('click', function() {
    console.log(i)
  });
}
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<div class="card-body">
  <!-- person -->
</div>

Etkinliğin her birini tıklatmasını h4 class="name"ve iilgili numarayı içeren bir günlüğü göstermesini istiyorum .

Bununla birlikte, console.logyalnızca son iilişkili olanı ( i=9bu durumda) gösterir ve diğer inumaralarla çalışmaz . Bu neden oluyor? Ne yapmam gerek?


3
Belki html-string'i geçmek yerine Document.createElement () kullanın ve çok daha kolay bir zamanınız olacak ve sonunda daha iyi kodla sonuçlanacağınızı düşünüyorum.
admcfajn

1
düğümleriniz arasında tekrar
dolaşmanız

Güzel soru, bu biraz zor, sanırım bir olay sonrası render attatch mümkün olabilir .. Örneğin fordöngü sonra bu öğelere olayları uygulamak için bir yöntem çağıran bir yöntem, ama bilmiyorum. test etmek jsFiddle olacak.
Pogrindis

İçin yetki verilen bir olay işleyici oluşturdu .card-bodyve elementin ( target) ile başlayan ve ID ile başlayan bir bağlantı olup olmadığını kontrol edin title.
hungerstar

1
Ah, cevap vermek üzereyim. Oy verildi reopen. Kapaklar gerekli değildir, sorun daha innerHTML += ...önce ayarlanmış olay dinleyicilerini öldürmektir, kapatmayı değil. document.createElementBunun yerine kullanın . Bu konuya
ggorlen

Yanıtlar:


8

innerHTMLhtml'nin tamamını yeniden çizer, sonuç olarak önceden eklenen tüm olaylar kaybolur. kullanıminsertAdjacentHTML()

for(let i=1;i<10;i++){
    document.querySelector('.card-body').insertAdjacentHTML('beforeend',`<div class="row" id="img_div">
        <div class="col-12 col-sm-12 col-md-2 text-center">
          <img src="http://placehold.it/120x80" alt="prewiew" width="120" height="80">
        </div>
        <div id="text_div" class="col-12 text-sm-center col-sm-12 text-md-left col-md-6">
        <h4 class="name"><a href="#" id="title`+i+`">Name</a></h4>
          <h4>
            <small>state</small>
          </h4>
          <h4>
            <small>city</small>
          </h4>
          <h4>
            <small>zip</small>
          </h4>
        </div>
        <div class="col-12 col-sm-12 text-sm-center col-md-4 text-md-right row">
        </div>
      </div>
     `);
   document.getElementById("title"+i).addEventListener('click', function () {
    console.log(i)
  });
}
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<div class="card-body">
<!-- person -->
</div>


3
Vay canına ... Ben simüler şeylerle uğraşıyordum ve bir zamanlar hiç insertAdjacentHTMLrastlayamadım - Her gün bir okul günü, gerçekten güzel.
Pogrindis

1
Çok havalı ve +1, ancak document.getElementByIdHTML'yi ekledikten hemen sonra kullanmak zorunda kalmak pahalı ve gereksiz görünüyor . Yüzlerce öğe ekliyorsanız, bu çok fazla çapraz iştir.
ggorlen

@ggorlen Sınıfı kullanarak nameve olayı sadece o sınıfa atlatarak, ilgi alanı dışındaki alan üzerinde anlaşmaya varıyorum (ya da belki sadece olayın kendisinden okuma) daha verimli olur mu?
Pogrindis

1
Emin değil. Gerçek kullanıma bağlı - önerim erken optimizasyon olabilir. Profil / kıyaslama yapmak ve görmek zorundasınız. Ama eğer document.createElementkullanılabiliyorsa, bence bu genellikle en iyi temel yaklaşımdır. Bu gönderi için bir başka olası gelişme, iki döngüyü kullanmaktır: biri tüm HTML'yi oluşturmak için, diğeri bir document.querySelectorAllçağrıda bir sınıf kullanarak tüm öğeleri yakalamak ve olay dinleyicilerini eklemek için.
ggorlen

1
Kesinlikle bir kriter, bu gece yapmak daha iyi bir şey düşünemiyorum! :)
Pogrindis

8

Kullanılması +=üzerine innerHTMLHTML içinde elemanlarında bunları tahrip olay dinleyicileri. Bunu yapmanın doğru yolu kullanmaktır document.createElement. İşte asgari, eksiksiz bir örnek:

for (let i = 1; i < 10; i++) {
  const anchor = document.createElement("a");
  document.body.appendChild(anchor);
  anchor.id = "title" + i;
  anchor.href= "#";
  anchor.textContent = "link " + i;
  document.getElementById("title" + i)
    .addEventListener("click", e => console.log(i));
}
a {
  margin-left: 0.3em;
}

Tabii ki, document.getElementByIdburada gerekli değildir , çünkü nesneyi döngü bloğunda oluşturduk. Bu, potansiyel olarak pahalı ağaç yürüyüşlerini kurtarır.

for (let i = 1; i < 10; i++) {
  const anchor = document.createElement("a");
  document.body.appendChild(anchor);    
  anchor.href= "#";
  anchor.textContent = "link " + i;
  anchor.addEventListener("click", e => console.log(i));
}
a {
  margin-left: 0.3em;
}

Örneğinizde olduğu gibi isteğe bağlı dizilmiş HTML parçalarınız varsa, bunu kullanabilir createElement("div"), bir innerHTMLkereliğine öbek olarak ayarlayabilir ve gerektiği gibi dinleyici ekleyebilirsiniz. Ardından div öğelerini kap öğenizin alt öğesi olarak ekleyin.

for (let i = 1; i < 10; i++) {
  const rawHTML = `<div><a href="#" id="link-${i}">link ${i}</a></div>`;
  const div = document.createElement("div");
  document.body.appendChild(div);
  div.href= "#";
  div.innerHTML = rawHTML;
  div.querySelector(`#link-${i}`)
    .addEventListener("click", e => console.log(i));
}


1
Düşündüğüm yaklaşım bu ve ellerimi bu çözümü verirdim, ama diğer cevap da harika.
Pogrindis

De cevap için teşekkürler, ama ben createElement ile düzeni oluşturmak için çalıştı ve başarısız oldu
Luiz Adorno

1
Sorun değil. Umarım HTML büyük bir parçasını varsa, bir gibi bir kök elemanı kapsayıcı oluşturmak için gerçekleştirmek <div>, sonra div.innerHTML += yourHugeChunkOfHTML. Bu nedenle, herhangi bir kullanım durumunda işe yaramaması için hiçbir neden yoktur.
ggorlen

1
Tavsiyenizle bu düzeni oluşturmaya çalışacağım, birkaç kez "document.getElementById" kullanmaktan ve performansı yavaşlatmaktan korkuyorum
Luiz Adorno
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.