简体   繁体   English

将EventListener 添加到innerHTML

[英]addEventListener to innerHTML

I am new to Javascript and I try to add an event listener for each button on every card, but the code make the last card (button) only have the event 'click' so is there's any way to make it happen with innerHTML card this is the code:我是 Javascript 的新手,我尝试为每张卡上的每个按钮添加一个事件侦听器,但代码使最后一张卡(按钮)只有事件“点击”所以有什么方法可以通过 innerHTML 卡实现它是代码:

let tracksRender = (track) => {

track.forEach(element => {

    //this the card that will add the button for
    let card = `<div class="card">
    <div class="image">
        <img class="image_img" src="${element.artwork_url || 'http://lorempixel.com/100/100/abstract/'}">
    </div >
        <div class="content">
            <div class="header">
                <a href="${element.permalink_url}" target="_blank">${element.title}</a>
            </div>
        </div>
</div >`;
    
    //here i add the card to DOM
    let searchResults = document.querySelector('.js-search-results');
    searchResults.innerHTML += card;

    // store the content of the button 
    let inBtn = `<i class="add icon"></i>
    <span>Add to playlist</span>`;
 
    // created button container 
    let btn = document.createElement("div");
    btn.classList.add("ui", "bottom", "attached", "button", "js-button");

    // added the content of the button 
    btn.innerHTML += inBtn;
    
    // here i add the the event Listener to the button 
    btn.addEventListener('click', () => {
        console.log("click");
    });

    //here i add the button to the last card have been created
    searchResults.querySelector(".card:last-child").append(btn);
    
});
}

and the structure:和结构:

<!doctype html>
<html>

<head>
    <meta charset='utf-8'>
    <meta name='viewport' content='width=device-width, initial-scale=1.0'>
    <title>SoundCloud Player</title>
    <link rel='stylesheet' href='https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.4.1/semantic.min.css'>
    <link rel='stylesheet' href='styles/main.css'>
    <style></style>
</head>

<body id="soundcloud-player">

    <div class="ui container col">
        <div class="col">
            <div class="main">
                <div class="js-search-results search-results ui cards">

                </div>
            </div>
        </div>
    </div>
    <script src="https://connect.soundcloud.com/sdk/sdk-3.3.2.js"></script>
    <script src='https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.4.1/semantic.min.js'></script>
    <script src="javascript/main.js"></script>
</body>

</html>

Fiddle: https://jsfiddle.net/y73bstju/7/小提琴: https://jsfiddle.net/y73bstju/7/

but it will add the event to the last card only但它只会将事件添加到最后一张卡片

It might help to create elements instead of appending innerHTML:它可能有助于创建元素而不是附加 innerHTML:

let tracksRender = (track) => {
    
  // Select the results here, so you wont have to repeat it
  const searchResults = document.querySelector('.js-search-results');

  track.forEach(element => {

    // Create the card, give it its class and innerHTML
    const card = document.createElement('div');
    card.className = 'card';
    card.innerHTML = `<div class="image">
                          <img class="image_img" src="${element.artwork_url || 'http://lorempixel.com/100/100/abstract/'}">
                      </div >
                      <div class="content">
                          <div class="header">
                              <a href="${element.permalink_url}" target="_blank">${element.title}</a>
                          </div>
                     </div>`;
 
    // Created the button, give its classes and innerHTML
    const btn = document.createElement('div');
    btn.className = 'ui bottom attached button js-button';
    btn.innerHTML = '<i class="add icon"></i><span>Add to playlist</span>';
    
    // Add the event listener
    btn.addEventListener('click', () => {
        console.log('click');
    });

    // Append the button to the created card
    card.appendChild(btn);

    // Add the card to the results
    searchResults.appendChild(card);
    
  });

}

I agree with you that theoretically the object should have the event, but the behavior we experience is that whenever another write happens at the relevant section of the DOM, the event handler is lost, which is the reason the last element has the click event.我同意你的观点,理论上 object 应该有事件,但我们遇到的行为是,每当在 DOM 的相关部分发生另一个写入时,事件处理程序就会丢失,这就是最后一个元素有点击事件的原因。 So, let's write first into the DOM and only when we are done with that should we add the event listeners, like:所以,让我们首先写入 DOM,只有当我们完成后我们才应该添加事件监听器,例如:

let SoundCloudAPI = {};
SoundCloudAPI.init = () => {
    SC.initialize({ client_id: 'cd9be64eeb32d1741c17cb39e41d254d' });
};
SoundCloudAPI.init();


SoundCloudAPI.getTrack = (inputVlue) => {
    SC.get('/tracks', {
        q: inputVlue
    }).then((tracks) => {
            console.log(tracks);
        SoundCloudAPI.renderTracks(tracks);
    });
}
SoundCloudAPI.getTrack("alan walker");

SoundCloudAPI.renderTracks = (track) => {

        track.forEach(element => {

    //this the card that will add the button for
    let card = `<div class="card">
    <div class="image">
        <img class="image_img" src="${element.artwork_url || 'http://lorempixel.com/100/100/abstract/'}">
    </div >
        <div class="content">
            <div class="header">
                <a href="${element.permalink_url}" target="_blank">${element.title}</a>
            </div>
        </div>
</div >`;
    
    //here i add the card to DOM
    let searchResults = document.querySelector('.js-search-results');
    searchResults.innerHTML += card;

    // store the content of the button 
    let inBtn = `<i class="add icon"></i>
    <span>Add to playlist</span>`;
 
    // created button container 
    let btn = document.createElement("div");
    btn.classList.add("ui", "bottom", "attached", "button", "js-button", "fresh");

    // added the content of the button 
    btn.innerHTML += inBtn;
    

    //here i add the button to the last card have been created
    searchResults.querySelector(".card:last-child").append(btn);
    });
    for (let btn of document.querySelectorAll('.ui.attached.button.js-button.fresh')) {
        // here i add the the event Listener to the button 
        btn.addEventListener('click', () => {
            console.log("click");
        });
    }
}

Fiddle: https://jsfiddle.net/r84um9pt/小提琴: https://jsfiddle.net/r84um9pt/

I think: you're doing:我认为:你正在做:

let searchResults = document.querySelector('.js-search-results');
searchResults.innerHTML += card;

Serializing again and again in your div "searchResults"在您的 div“searchResults”中一次又一次地序列化

innerHTML ~erases~ listeners, and probably it is ~erasing~ your previous listeners. innerHTML ~erases~ listeners,可能它正在 ~erasing~ 你以前的听众。 Besides, i don't remember where i read that innerHTML script code cannot run (for security purposes)此外,我不记得我在哪里读到 innerHTML 脚本代码无法运行(出于安全目的)

From https://medium.com/@kevinchi118/innerhtml-vs-createelement-appendchild-3da39275a694来自https://medium.com/@kevinchi118/innerhtml-vs-createelement-appendchild-3da39275a694

using innerHTML reparses and recreates all DOM nodes inside the div element and is less efficient than simply appending a new element to the div.使用 innerHTML 会重新解析并重新创建 div 元素内的所有 DOM 节点,并且比简单地将新元素附加到 div 效率低。 In the above cases, createElement is the more performant choice.在上述情况下,createElement 是性能更高的选择。

Be careful:当心:

Using "append" again and again uses badly browser resources, redrawing many times.一次又一次地使用“追加”会严重使用浏览器资源,重绘多次。 But, you can append in a documentFragment and append it to the div -js-search-results但是,您可以 append 在 documentFragment 和 append 到 div -js-search-results

DocumentFragment: https://developer.mozilla.org/es/docs/Web/API/DocumentFragment文档 片段:https://developer.mozilla.org/es/docs/Web/API/DocumentFragment

Welcome in the community.欢迎加入社区。 In you're code you're adding many classes to button.在您的代码中,您正在向按钮添加许多类。 You can add event Listener to any one of the unique class name which is specifically applied on button element only.您可以将事件侦听器添加到唯一的 class 名称中的任何一个,该名称仅适用于按钮元素。

You can replace:您可以更换:

btn.addEventListener('click', () => {
    console.log('click');
});

with:和:

document.querySelectorAll('.js-button').forEach(el=>{
  el.addEventListener('click', (event) => {
  event.preventDefault();
  console.log("click");
 });
});

Also, it would be good if you add eventListener out of the loop in which you are appending elements.此外,如果您在添加元素的循环之外添加 eventListener 会很好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM