下面是能用的迷你待办清单:点条目切换完成、点 × 删除;后面几节还会对它做实验。
let tasks = [
{ text: '写周报', done: true },
{ text: '修登录 bug', done: false }
]
function renderTasks() {
todo.replaceChildren() // 先清空(比 innerHTML = '' 更现代)
tasks.forEach((task, index) => {
const li = document.createElement('li') // 造
li.className = task.done ? 'item done' : 'item'
li.dataset.index = index // 把「第几项」记在 DOM 上
const txt = document.createElement('span')
txt.className = 'txt'
txt.textContent = task.text // 用户输入永远走 textContent
li.append(txt) // 拼
todo.append(li) // 挂
})
}
todo.addEventListener('click', (e) => {
const li = e.target.closest('.item') // 事件委托:点在谁身上都能找回 li
if (!li) return
const index = Number(li.dataset.index)
tasks[index].done = !tasks[index].done // 改数据,然后重建
renderTasks()
})
el.textContent = '<b>加粗</b>' // 原样当纯文本:页面上就是这串字符 el.innerHTML = '<b>加粗</b>' // 交给浏览器解析:真的变成加粗文字 // 铁律:挂「用户输入」永远走 textContent; // innerHTML 只用于你完全掌控的模板字符串(否则就是 XSS 入口)
li.classList.add('flag') // 加
li.classList.remove('flag') // 删
li.classList.toggle('flag') // 有则删、无则加,返回最终是否含有
li.classList.contains('flag') // 判断 → true / false
li.dataset.index = 2 // 写 data-index="2"
li.dataset.index // 读回来,只拿到字符串
li.remove() // 从 DOM 树里摘掉自己 list.replaceChildren() // 清空全部子节点 // 注意:这类「直接删节点」绕过了数据—— // 下一次 renderTasks() 重建,删掉的项会「复活」。数据才是真相源。