Javascript 如何使用JS created按钮删除JS created LI?
我正在用JavaScript创建一个TODO应用程序。我如何理解如何链接两个创建的JavaScript项并将它们从DOM中删除 TL;DR:我经常遇到的问题是在创建列表项后在DOM中导航。我曾尝试对创建的元素使用一个带有“id”标记的setAttribute,但我仍然能够找到如何迭代LI来查找按下了哪个按钮 代码:Javascript 如何使用JS created按钮删除JS created LI?,javascript,html,dom,Javascript,Html,Dom,我正在用JavaScript创建一个TODO应用程序。我如何理解如何链接两个创建的JavaScript项并将它们从DOM中删除 TL;DR:我经常遇到的问题是在创建列表项后在DOM中导航。我曾尝试对创建的元素使用一个带有“id”标记的setAttribute,但我仍然能够找到如何迭代LI来查找按下了哪个按钮 代码: <div class="entry-field"> <label class="task-input" for="task-in
<div class="entry-field">
<label class="task-input" for="task-input">Task:</label>
<input type="text" class="task-field" placeholder="Enter Item"/>
<button class="add-btn">ADD</button>
</div>
<section class="task-list">
<h2>Task List</h2>
<div class="list-wrap"></div>
<ul class="item-log">
<li class="list-item">
<span class="item-text">this is the item</span>
<button class="delete-btn">delete</button>
</li>
</ul>
</div>
</section>
</main>
JavaScript:
let index = 0;
//Obtaining user text, creating a Span element, append span with user text:
function addItem() {
let itemLog = document.querySelector(".item-log");
let listItem = document.createElement("LI");
let deleteBtn = document.createElement("BUTTON");
let userEntry = document.querySelector(".task-field").value;
let spanItem = document.createElement("SPAN");
index++;
//Creating LI "list-item" and append UL "itemLog"
itemLog.appendChild(listItem);
listItem.classList.add("list-item");
listItem.setAttribute("id", index);
//Create Span element, assign text from user input, append LI
spanItem.innerHTML = userEntry;
listItem.appendChild(spanItem);
//Create deleteBtn and append to LI
deleteBtn.innerHTML = "Delete";
deleteBtn.classList.add("delete-btn");
deleteBtn.setAttribute("onclick", "deleteItem()");
deleteBtn.setAttribute("id", index);
listItem.appendChild(deleteBtn);
userEntry.value = "";
}
/*
2) Deleting item from list:
-use event listener to trigger parent node
-delete child
*/
function deleteItem() {
let listItem = this.parentElement;
listItem.parentElement.removeChild(listItem);
}
// Page event listeners
let addBtn = document.querySelector(".add-btn");
addBtn.addEventListener("click", addItem);
任务:
添加
任务列表
-
这是项目
删除
JavaScript:
设指数=0;
//获取用户文本、创建Span元素、使用用户文本附加Span:
函数addItem(){
让itemLog=document.querySelector(“.itemLog”);
让listItem=document.createElement(“LI”);
让deleteBtn=document.createElement(“按钮”);
让userEntry=document.querySelector(“.task field”).value;
设spanItem=document.createElement(“SPAN”);
索引++;
//创建LI“列表项”并附加UL“项目日志”
appendChild(listItem);
listItem.classList.add(“列表项”);
setAttribute(“id”,索引);
//创建Span元素,根据用户输入指定文本,追加LI
spanItem.innerHTML=userEntry;
listItem.appendChild(spanItem);
//创建deleteBtn并附加到LI
deleteBtn.innerHTML=“删除”;
deleteBtn.classList.add(“deleteBtn”);
setAttribute(“onclick”,“deleteItem()”);
deleteBtn.setAttribute(“id”,索引);
listItem.appendChild(deleteBtn);
userEntry.value=“”;
}
/*
2) 正在从列表中删除项目:
-使用事件侦听器触发父节点
-删除子项
*/
函数deleteItem(){
让listItem=this.parentElement;
listItem.parentElement.removeChild(listItem);
}
//页面事件侦听器
让addBtn=document.querySelector(“.addBtn”);
addBtn.addEventListener(“单击”,添加项);
您的示例中的问题是这个
在您的删除项
函数中所指的内容。如果您在deleteItem
功能中记录console.log,您将看到此
指的是窗口,而不是按下的按钮
如果不使用setAttribute
设置onClick
,您可以添加一个事件侦听器:
deleteBtn.addEventListener(“单击”,删除项)代码>
在deleteItem
函数中,您可以访问事件对象以及该事件的目标,并且代码将按预期工作
function deleteItem(event) {
let listItem = event.target.parentElement;
listItem.parentElement.removeChild(listItem);
}
在任何鼠标事件侦听器上,始终会有一个MouseEvent
参数传递给事件处理程序。该MouseEvent
对象具有属性target
,该属性是作为事件目标的HTMLElement
。例如:
let div=document.querySelector('div.button');
设toggleState=0;
让消息=[“单击!”,“单击我!”;
let handler=函数(事件){
event.target.innerText=消息[toggleState];
切换状态^=1;
}
div.addEventListener(“单击”,处理程序,false)代码>
点击我代码>
- 在创建删除元素时指定一个单击处理程序
- 创建要预填充的任务数组
const myTasks=[
“这是物品”,
“嗯,这是另一项”
];
const EL_text=document.querySelector(“#text”);
const EL#u add=document.querySelector(“#add”);
const EL_tasks=document.querySelector(“#tasks”);
函数addTask(文本){
//确定是否有文本字符串参数(预填充)
//否则,获取输入值:
text=typeof text===“string”?text:EL_text.value.trim();//修剪您的值!
if(!text)return;//如果没有值,则不执行任何操作!
const EL_task=document.createElement('li');
const EL_delete=document.createElement('button');
EL_delete.textContent=“删除”;
EL_delete.addEventListener('click',()=>EL_task.remove());
EL_task.insertAdjacentHTML('afterbegin','${text}');
EL_task.appendChild(EL_delete);
EL_tasks.appendChild(EL_task);
EL_text.value='';//清除当前输入文本值
}
EL_add.addEventListener(“单击”,添加任务);
//预填充
myTasks.forEach(addTask)代码>
#任务{
填充:0;
列表样式:无;
}
#任务李{
显示器:flex;
背景:#eee;
填充:0.6em;
边缘底部:0.5em;
边界半径:0.4em;
}
#李分区{
弹性:1;
}
任务:
添加
在创建必须动态插入类似元素并通过ID系统跟踪它们的应用程序时,我建议使用一种更有条理的方法来消除代码中的任何混乱
对于基本应用程序,您可以创建自定义类,每个类都有元素
、模板
、ui
、uiEventCallbacks
、切换uievents
和呈现
方法。在每个类中,元素
将是一个包含模板
标记的主HTML元素。render
方法解析模板
文本并将其分配给元素.innerHTML
。要实例化应用程序,只需创建基类的新实例,呈现它,然后将元素附加到主体
我用您的标记创建了一个Todo应用程序。有TodoApp
、Todo
和Todo
类。TodoApp
包含Todo
,而Todo
包含Todo
的实例
待办事项
const Todo = class {
constructor(settings) {
this.settings = settings
}
get settings() { return this._settings }
set settings(settings) { this._settings = settings }
get element() {
if(!this._element) {
this._element = document.createElement('li')
this._element.setAttribute('class', 'list-item')
this._element.setAttribute('id', this.settings.id )
}
return this._element
}
get ui() { return {
deleteButton: this.element.querySelectorAll(':scope > .delete-btn'),
} }
get uiEventCallbacks() { return {
deleteButtonClick: (event) => {
let customEvent = new CustomEvent('removeTodo', {
bubbles: true,
details: {
id: this.settings.id
}
})
this.element.dispatchEvent(
customEvent
)
},
} }
remove() {
this.element.parentElement.removeChild(this.element)
}
template() { return `
<span>${this.settings.value}</span>
<button class="delete-btn">Delete</button>
` }
toggleUIEvents() {
[
'removeEventListener',
'addEventListener'
].forEach((eventMethod) => {
this.ui.deleteButton.item(0)[eventMethod]('click', this.uiEventCallbacks.deleteButtonClick)
})
}
render() {
const template = this.template()
this.element.innerHTML = template
this.toggleUIEvents()
return this
}
}
const Todos = class {
constructor() {}
get element() {
if(!this._element) {
this._element = document.createElement('section')
this._element.setAttribute('class', 'task-list')
}
return this._element
}
get ui() { return {
itemLog: this.element.querySelectorAll('.item-log')
} }
get uiEventCallbacks() { return {
removeTodo: (event) => {
console.log(event)
this.removeTodo()
},
} }
get todos() {
this._todos = this._todos || []
return this._todos
}
template() { return `
<h2>Task List</h2>
<div class="list-wrap">
<ul class="item-log"></ul>
</div>
` }
toggleUIEvents() {
[
'removeEventListener',
'addEventListener'
].forEach((eventMethod) => {
this.ui.itemLog.item(0)[eventMethod]('removeTodo', this.uiEventCallbacks.removeTodo)
})
}
addTodo(data) {
const todo = new Todo(data)
this.todos.push(todo)
this.ui.itemLog.item(0).appendChild(
todo.render().element
)
return this
}
removeTodo(id) {
let todoIndex = this.todos.reduce((_todoIndex, todo, todoIndex) => {
if(todo.id === id) _todoIndex = todoIndex
return _todoIndex
}, -1)
let todo = this.todos.splice(todoIndex, 1)[0]
todo.remove()
return this
}
render(data) {
const template = this.template(data)
this.element.innerHTML = template
this.toggleUIEvents()
return this
}
}
const TodoApp = class {
constructor() {}
get element() {
if(!this._element) {
this._element = document.createElement('main')
}
return this._element
}
get ui() { return {
addButton: this.element.querySelectorAll('.add-btn'),
input: this.element.querySelectorAll('.task-field'),
} }
get uiEventCallbacks() { return {
addTodo: (event) => {
let taskFieldData = this.ui.input.item(0).value
this.todos.addTodo({
id: this.uuid(),
value: taskFieldData,
})
},
} }
get todos() {
this._todos = this._todos || new Todos()
return this._todos
}
uuid() {
var uuid = '', i, random
for (i = 0; i < 32; i++) {
random = Math.random() * 16 | 0
if (i === 8 || i === 12 || i === 16 || i === 20) {
uuid += "-"
}
uuid += (i === 12 ? 4 : (i === 16 ? (random & 3 | 8) : random)).toString(16)
}
return uuid
}
template() { return `
<div class="entry-field">
<label class="task-input" for="task-input">Task:</label>
<input type="text" class="task-field" placeholder="Enter Item"/>
<button class="add-btn">ADD</button>
</div>
` }
toggleUIEvents() {
[
'removeEventListener',
'addEventListener'
].forEach((eventMethod) => {
this.ui.addButton.item(0)[eventMethod]('click', this.uiEventCallbacks.addTodo)
})
}
render(data) {
const template = this.template(data)
this.element.innerHTML = template
this.element.appendChild(this.todos.render().element)
this.toggleUIEvents()
return this
}
}
谢谢你的帮助。这是一个简单的解决方案。理解这个解决方案时,我的问题是:为什么delete函数必须放在addItem()函数中?我假设它与范围有关,但我不明白为什么它不能在功能之外为或生存
const todoApp = new TodoApp()
const body = document.querySelector('body')
body.insertAdjacentElement('afterbegin', todoApp.render().element)