如何访问JS中新创建的DOM元素? (我已经使用了附录)

发布于 2025-02-11 16:54:49 字数 1808 浏览 0 评论 0 原文

我正在做一个待办事项清单。每个列表项目都在创建时包含一个删除按钮。

但是我无法在脚本中访问这些删除按钮,因为尽管我使用了“ .appendchild”,但它不包含在DOM中。谁能帮忙?

const buttonSubmit = document.querySelector('#button-submit');
const form = document.querySelector('form');
const icons = document.querySelector('#icons');
let toDoList = document.querySelector('#todolist');
const input = document.querySelector('#formtext');

form.addEventListener('submit', (e) => {
  e.preventDefault();

  const newListItem = document.createElement('li');

  newListItem.innerHTML = '<span>' + input.value + '</span>' +
    '<span id="icons">' +
    '<button id="check" class="buttonlist">' + '<img src="checked.png" alt="">' + '</button>' +
    '<button id="remove" class="buttonlist">' + '<img src="remove.png" alt="">' + '</button>' +
    '<button id="edit" class="buttonlist">' + '<img src="edit.png" alt="">' + '</button>' + '</span>';

  toDoList.appendChild(newListItem);
  form.reset();
})

const buttonCheck = document.querySelector('#check');
const buttonEdit = document.querySelector('#edit');
const buttonRemove = document.getElementById('remove');

buttonRemove.addEventListener('click', function() {
  alert('remove list item');
})
<div class="container-box">
  <h1>To Do List</h1>
  <br>

  <form action="">

    <input type="text" id="formtext" name="formtext">

    <button id="button-submit">Add Item</button>

  </form>
  <br><br><br><br>

  <!-- Dynamic list here -->
  <ul id="todolist"> </ul>
</div>

I am making a to do list. Each list item includes a remove button when created.

But I cannot access these remove buttons in my script, because it is not included in my DOM, although I used '.appendChild'. Can anyone help?

const buttonSubmit = document.querySelector('#button-submit');
const form = document.querySelector('form');
const icons = document.querySelector('#icons');
let toDoList = document.querySelector('#todolist');
const input = document.querySelector('#formtext');

form.addEventListener('submit', (e) => {
  e.preventDefault();

  const newListItem = document.createElement('li');

  newListItem.innerHTML = '<span>' + input.value + '</span>' +
    '<span id="icons">' +
    '<button id="check" class="buttonlist">' + '<img src="checked.png" alt="">' + '</button>' +
    '<button id="remove" class="buttonlist">' + '<img src="remove.png" alt="">' + '</button>' +
    '<button id="edit" class="buttonlist">' + '<img src="edit.png" alt="">' + '</button>' + '</span>';

  toDoList.appendChild(newListItem);
  form.reset();
})

const buttonCheck = document.querySelector('#check');
const buttonEdit = document.querySelector('#edit');
const buttonRemove = document.getElementById('remove');

buttonRemove.addEventListener('click', function() {
  alert('remove list item');
})
<div class="container-box">
  <h1>To Do List</h1>
  <br>

  <form action="">

    <input type="text" id="formtext" name="formtext">

    <button id="button-submit">Add Item</button>

  </form>
  <br><br><br><br>

  <!-- Dynamic list here -->
  <ul id="todolist"> </ul>
</div>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

花开雨落又逢春i 2025-02-18 16:54:49

问题

ID必须是唯一的,每次您将任务添加到列表中时 - 第一个后,一切都是无效的HTML。当针对ID时,浏览器会找到第一个ID,然后停止并忽略重复ID。为任何重复的标签使用类和/或名称属性。

删除按钮不起作用的原因是因为在不存在时定义了对按钮的引用。

此外

// After page is loaded...
const buttonRemove = document.getElementById('remove');
// Console will tell you buttonRemove is null
// User has not entered any data nor has user clicked the add button

​/strong>仅适用于第一个按钮。

图II

buttonRemove.addEventListener('click', function() {
  alert('remove list item'); // Don't use alert() use console.log()
})

解决方案

参考标签 是创建它们的。在OP( o igninal p ost)中,&lt; li&gt; 的内容是呈现的,这使得新创建的标签有问题加上htmlstring如果在大多数情况下是可行且实用的,则应避免与动态创建的标签结合。

要处理未知数量的动态创建标签的事件,请将事件绑定到静态祖先标签,在OP中,该标签是&lt; ul&gt; 或任何其父母标签(甚至&lt; Body&gt; 文档窗口,但最好尽可能接近)。然后将其进行使事件处理程序控制哪个标签响应以及如何响应。有关更多详细信息,请参见附录

有两个示例:

示例a - 修订的OP代码

示例B - 使用 htmlformelement 接口,请参见 appendix

两个示例都评论了逐步的详细信息

示例

// Reference <form>, <ul>, and <input>
const form = document.querySelector('form');
const list = document.querySelector('ul');
const input = document.querySelector('#text');

// Bind <form> to submit event
form.addEventListener('submit', (e) => {
  // Stop default behavior of <form> during submit ecent
  e.preventDefault();
  // Create <li> and <output>
  const item = document.createElement('li');
  const out = document.createElement('output');
  // Assign value of <input> to the value of <output>
  out.value = input.value;
  // Add <output> to <li> -- <li> to <ul>
  item.append(out);
  list.append(item);
  /*
  Run a for loop 3 times -- on each iteration...
  ...create an <input> and assign type as "button"...
  ...buttons [name] and [value] is determined by current index...
  ...add button to <li>
  */
  for (let i = 0; i < 3; i++) {
    let btn = document.createElement('input');
    btn.type = 'button';
    let cmd = i === 0 ? 'done' : i === 1 ? 'edit' : i === 2 ? 'remove' : false;
    btn.name = cmd;
    btn.value = cmd;
    item.append(btn);
  }
  // Reset <form>
  form.reset();
});

// Bind <ul> to click event
list.addEventListener('click', manageList);

// Event handler always passes event object by default
function manageList(e) {
  // Reference the tag user clicked
  const clk = e.target;
  // If user clicked a remove button remove it's parent tag
  if (clk.name === 'remove') {
    clk.parentElement.remove();
  }

  if (clk.name === 'edit') {
    console.log('EDIT');
  }

  if (clk.name === 'done') {
    console.log('DONE');
  }
}
li {
  display: flex;
  align-items: center
}

[type='button'] {
  text-transform: capitalize
}
<form>
  <input id="text" name="text" type="text">
  <button>Add Item</button>
</form>
<br>
<ul></ul>

示例b

// Bind <form> to click event
document.forms.todo.onclick = taskList;
// Event handler akways passes the event object
function taskList(e) {
  // Reference the tag user clicked
  const clk = e.target;
  // Reference all form controls
  const IO = this.elements;
  /*
  If the user clicked the add button...
  ...reference the <ul>...
  ...create <li> and <output>...
  ...add text from <input> to <output>...
  ...add <output> to <li>...
  ...Run a for loop 3 times -- on each iteration...
  ...create an <button> and assign type as "button"...
  ...buttons [name] and text is determined by current index...
  ...add button to <li>...
  ...add <li> to <ul>...
  ...clear <input>
  */
  if (clk.name == 'add') {
    const list = IO.list.firstElementChild;
    const item = document.createElement('li');
    const text = document.createElement('output');
    text.value = IO.data.value;
    item.append(text);
    for (let i = 0; i < 3; i++) {
      let btn = document.createElement('button');
      btn.type = 'button';
      let cmd = i === 0 ? 'done' : i === 1 ? 'edit' : i === 2 ? 'remove' : false;
      btn.name = cmd;
      btn.textContent = cmd;
      item.append(btn);
    }
    list.append(item);
    IO.data.value = '';
  }
  /*
  If the user clicked a remove button...
  ...find the <li> ancestor of remove button and remove 
  it thereby removing the <output> and itself as well
  */
  if (clk.name === 'remove') {
    clk.closest('li').remove();
  }
  if (clk.name === 'done') {
    console.log('DONE');
  }
  if (clk.name === 'edit') {
    console.log('EDIT');
  }
}
<form id='todo'>
  <input id='data' required><button name='add' type='button'>Add</button>
  <fieldset id='list'>
    <ul></ul>
  </fieldset>
</form>

附录

evest

/DEVELECTER.MOZILLA.org/en-us/docs/learn/javascript/building_blocks/events#event_delegation“ rel =“ nofollow noreferrer”> event develegation

htmlformelement

Problems

ids must be unique, every time you add a task to the list -- after the first one everything is invalid HTML. When directed to an id the browser will find the first id then stop and ignore the duplicate ids. Use class and/or name attributes for any replicated tags.

The reason why the remove button doesn't work is because the reference to the button was defined when it didn't exist.

Figure I

// After page is loaded...
const buttonRemove = document.getElementById('remove');
// Console will tell you buttonRemove is null
// User has not entered any data nor has user clicked the add button

Moreover, even if that was fixed by referencing the button after it was created, binding it as shown on Figure II will only work for the first button only.

Figure II

buttonRemove.addEventListener('click', function() {
  alert('remove list item'); // Don't use alert() use console.log()
})

Solution

Reference tags after they are created. In the OP (Original Post), the contents of the <li> is rendered htmlString which makes referencing newly created tags problematic plus binding to dynamically created tags individually should be avoided if it's feasible and practical in which in most cases it is.

To handle events for an unknown amount of dynamically created tags, bind the event to a static ancestor tag, which in the OP is <ul> or any of it's parent tags (even <body>, document, and window but it's best to be as close as possible). Then make it so the event handler controls which tags respond and how. See Appendix located at the very end of this answer for more details.

There are two examples:

Example A - revised OP code

Example B - a todo list using HTMLFormElement interface, see Appendix

Both examples have commented step-by-step details

Example A

// Reference <form>, <ul>, and <input>
const form = document.querySelector('form');
const list = document.querySelector('ul');
const input = document.querySelector('#text');

// Bind <form> to submit event
form.addEventListener('submit', (e) => {
  // Stop default behavior of <form> during submit ecent
  e.preventDefault();
  // Create <li> and <output>
  const item = document.createElement('li');
  const out = document.createElement('output');
  // Assign value of <input> to the value of <output>
  out.value = input.value;
  // Add <output> to <li> -- <li> to <ul>
  item.append(out);
  list.append(item);
  /*
  Run a for loop 3 times -- on each iteration...
  ...create an <input> and assign type as "button"...
  ...buttons [name] and [value] is determined by current index...
  ...add button to <li>
  */
  for (let i = 0; i < 3; i++) {
    let btn = document.createElement('input');
    btn.type = 'button';
    let cmd = i === 0 ? 'done' : i === 1 ? 'edit' : i === 2 ? 'remove' : false;
    btn.name = cmd;
    btn.value = cmd;
    item.append(btn);
  }
  // Reset <form>
  form.reset();
});

// Bind <ul> to click event
list.addEventListener('click', manageList);

// Event handler always passes event object by default
function manageList(e) {
  // Reference the tag user clicked
  const clk = e.target;
  // If user clicked a remove button remove it's parent tag
  if (clk.name === 'remove') {
    clk.parentElement.remove();
  }

  if (clk.name === 'edit') {
    console.log('EDIT');
  }

  if (clk.name === 'done') {
    console.log('DONE');
  }
}
li {
  display: flex;
  align-items: center
}

[type='button'] {
  text-transform: capitalize
}
<form>
  <input id="text" name="text" type="text">
  <button>Add Item</button>
</form>
<br>
<ul></ul>

Example B

// Bind <form> to click event
document.forms.todo.onclick = taskList;
// Event handler akways passes the event object
function taskList(e) {
  // Reference the tag user clicked
  const clk = e.target;
  // Reference all form controls
  const IO = this.elements;
  /*
  If the user clicked the add button...
  ...reference the <ul>...
  ...create <li> and <output>...
  ...add text from <input> to <output>...
  ...add <output> to <li>...
  ...Run a for loop 3 times -- on each iteration...
  ...create an <button> and assign type as "button"...
  ...buttons [name] and text is determined by current index...
  ...add button to <li>...
  ...add <li> to <ul>...
  ...clear <input>
  */
  if (clk.name == 'add') {
    const list = IO.list.firstElementChild;
    const item = document.createElement('li');
    const text = document.createElement('output');
    text.value = IO.data.value;
    item.append(text);
    for (let i = 0; i < 3; i++) {
      let btn = document.createElement('button');
      btn.type = 'button';
      let cmd = i === 0 ? 'done' : i === 1 ? 'edit' : i === 2 ? 'remove' : false;
      btn.name = cmd;
      btn.textContent = cmd;
      item.append(btn);
    }
    list.append(item);
    IO.data.value = '';
  }
  /*
  If the user clicked a remove button...
  ...find the <li> ancestor of remove button and remove 
  it thereby removing the <output> and itself as well
  */
  if (clk.name === 'remove') {
    clk.closest('li').remove();
  }
  if (clk.name === 'done') {
    console.log('DONE');
  }
  if (clk.name === 'edit') {
    console.log('EDIT');
  }
}
<form id='todo'>
  <input id='data' required><button name='add' type='button'>Add</button>
  <fieldset id='list'>
    <ul></ul>
  </fieldset>
</form>

Appendix

Events

Event delegation

HTMLFormElement

HTMLFormControlsCollection

Form Controls

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文