简体   繁体   中英

Javascript onclick event listners works only sometimes

So, I'm trying to add an "edit" button before dynamic "post" is shown in the <div> . I want to add event listener to this "edit" button when clicked. However, it works as desired(onclick works and "edit clicked" is printed on console) only when I append this "edit" at certain position in my code(code-2), ie, when there is no change to the innerHTML of parent <div> after appending this button, but that's not how the UI is demanded.

When it is not working, CODE-1(this is where I want "edit" in UI)

let post_div = document.createElement('div');
let edit = document.createElement('div');
edit.style.color = 'blue';
edit.innerHTML = 'Edit';
post_div.append(edit);
let htmlsegment2 = `
    <div id="post-data">${post.post_data}</div>
    <div style="color: grey;">${post.timestamp}</div>`;
post_div.innerHTML += htmlsegment2;
edit.onclick = function(){
    console.log("edit clicked");
}
post_div.className = 'all-posts';
document.querySelector('#all-posts').append(post_div);

When I change the position of appended line, it starts working CODE-2

let post_div = document.createElement('div');
let edit = document.createElement('div');
edit.style.color = 'blue';
edit.innerHTML = 'Edit';
let htmlsegment2 = `
      <div id="post-data">${post.post_data}</div>
      <div style="color: grey;">${post.timestamp}</div>`;
post_div.innerHTML += htmlsegment2;
 edit.onclick = function(){
      console.log("edit clicked");
}   
post_div.append(edit);
post_div.className = 'all-posts';
document.querySelector('#all-posts').append(post_div);

The key difference is the order of these 2 statements, which is different between the two examples:

1:

post_div.append(edit);

2:

post_div.innerHTML += htmlsegment2;

In the first (non-working) snippet, 1) happens first, then 2). The problem here is that 2) completely replaces the innerHTML of the post_div . It replaces it with a copy of what was there before, with the content of htmlsegment2 added at the end. It's just a shorthand for:

post_div.innerHTML = post_div.innerHTML + htmlsegment2;

and hopefully seeing it in that form makes it clearer that the entire innerHTML gets thrown away and then replaced. Although the result will still contain the same HTML content, it importantly won't maintain the presence of the DOM element you've called edit as a child of post_div . This means that when you later set edit.onclick , you're setting an attribute of an element that isn't actually in the DOM - therefore nothing noticeable actually happens.

In the second snippet, 2) happens first, which means that edit is appended to post_div and not replaced thereafter - so any manipulations of edit do apply to an element in the actual DOM.

Hopefully that makes sense as to what the difference is between the two snippets. I would say as a general point that your code has some issues - assigning strings of HTML directly to the innerHTML property isn't very maintainable, and using the += operator with innerHTML has some common gotchas, of which your question is an example (and it's also quite inefficient). And it's much better to use the addEventListener method than assign to the onclick property (although both are much better than inline event listeners in HTML, admittedly).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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