第三章 浏览器
4. 文本、表单的增删改查
4.1 通过点击按钮实现段落的增加
<div class="box"><h1>一个标题</h1><h1>一个标题</h1><h1>一个标题</h1></div><button id="btn">新增</button><script>let box = document.querySelector('.box')btn.onclick = function () {// box.innerHTML = box.innerHTML +"<p>段落</p>”//性能不好// 创建一个p节点元素let $p = document.createElement('p')console.log($p);console.dir($p);// 插入信息$p.innerText = '段落'$p.className = 'txt'// 渲染到视图box.append($p)}</script>
4.2 通过点击表单的不同按钮,实现表单的不同操作
表单html格式
<!--数据表格 --><table border="1"><thead><tr><th>编号</th><th>姓名</th><th>年龄</th><th>职业</th><th>操作</th></tr></thead><tbody><tr><td>1</td><td>张三</td><td>18</td><td>学生</td><td><button>编辑</button><button class="del" onclick="delTr(this)">删除</button></td></tr><tr><td>2</td><td>张三</td><td>18</td><td>学生</td><td><button>编辑</button><button class="del" onclick="delTr(this)">删除</button></td></tr></tbody></table><hr><!--表单--><div class="main">姓名:<input name="uname" type="text" value="超级管理员"><br />年龄:<input name="uage" type="text"><br />职业:<input name="ujob" type="text"><br /><button id="btn">提交</button></div>
JS实现的功能
<script>/*新增功能 *///查找let uname = document.getElementsByName('uname')[0]let uage = document.getElementsByName('uage')[0]let ujob = document.getElementsByName('ujob')[0]let btn = document.getElementById('btn')let tableBody = document.querySelector("table tbody")// console.log(ujob);// console.log(tableBody);let delTrs = document.querySelectorAll(".del")console.log(delTr);// 点击的时候读取数据btn.onclick = function () {console.log(uname.value);console.log(uage.value);console.log(ujob.value);// 插入到表格内部let $tr = document.createElement('tr')$tr.innerHTML = `<td>${Date.now()}</td><td>${uname.value}</td><td>${uage.value}</td><td>${ujob.value}</td><td><button>编辑</button><button class="del" onclick="delTr(this)">删除</button></td>`tableBody.append($tr)// 清空uname.value = ''uage.value = ''ujob.value = ''}//删除行function delTr(btn){console.log("删除");console.log(btn);// append 添加 remove 删除btn.parentElement.parentElement.remove()}</script>
1. 第一个难点:我们来详细分析一下你提供的 HTML 代码中 删除功能是如何运行的。
🔍 删除功能的核心代码
<button class="del" onclick="delTr(this)">删除</button>
以及对应的 JavaScript 函数:
function delTr(btn) {console.log("删除");console.log(btn);btn.parentElement.parentElement.remove();
}
✅ 删除功能运行步骤解析
1️⃣ onclick="delTr(this)"
的作用
- 当用户点击“删除”按钮时,会触发
onclick
事件。 this
指的是当前被点击的 DOM 元素 —— 即这个<button>
按钮本身。- 所以
delTr(this)
就是把当前按钮作为参数传入delTr
函数。
例如:
<button class="del" onclick="delTr(this)">删除</button>
点击后调用:
delTr(这个按钮元素)
2️⃣ delTr(btn)
函数做了什么?
function delTr(btn) {console.log("删除");console.log(btn); // 打印传入的按钮元素btn.parentElement.parentElement.remove();
}
我们逐步拆解这行关键代码:
表达式 | 含义 |
---|---|
btn | 当前点击的“删除”按钮(<button> 元素) |
btn.parentElement | 按钮的父元素 → 是 <td> (包含“编辑”和“删除”按钮的那个单元格) |
btn.parentElement.parentElement | <td> 的父元素 → 是 <tr> (整行数据行) |
.remove() | 调用 DOM 方法,将该 <tr> 从页面中彻底删除 |
✅ 所以最终结果是:删除了当前按钮所在的那一整行表格数据。
✅ 总结
问题 | 回答 |
---|---|
删除是怎么运行的? | 用户点击“删除”按钮 → 触发 delTr(this) → 传入按钮自身 → 通过 parentElement.parentElement 找到所在行 <tr> → 调用 .remove() 删除整行 |
关键原理 | 利用 DOM 层级关系向上查找父元素,最终删除 <tr> |
推荐改进 | 使用 btn.closest('tr').remove() 更简洁安全 |
2. 第二个难点:JS中,删除函数 delTr 为什么不能改
其实要分情况讨论:这个函数在当前代码中是可以改的,但有一些限制和注意事项,否则就会出错或失效。
下面我们来详细解释:
✅ 一、delTr
函数 可以改!
你完全可以修改它的名字、逻辑、行为,只要保证:
- HTML 中调用的名字也同步修改
- 函数仍然能正确删除对应的行
✅ 例子:你可以改成 deleteRow
function deleteRow(btn) {btn.parentElement.parentElement.remove();
}
同时,必须修改 HTML 中的 onclick
:
<!-- 改成 -->
<button class="del" onclick="deleteRow(this)">删除</button>
✅ 这样就能正常运行,而且更语义化。
⚠️ 二、为什么“感觉不能改”?—— 实际限制
虽然可以改,但在你当前的代码结构下,有以下几个 硬性依赖,导致你不能随意改:
❌ 限制 1:HTML 内联事件写死了函数名
onclick="delTr(this)"
只要你把 JS 里的函数名从
delTr
改成别的(比如removeTr
),但没改 HTML 里的名字,就会报错:Uncaught ReferenceError: delTr is not defined
👉 所以你必须 同时改 JS 函数名 和 HTML 中的调用名。
❌ 限制 2:函数参数必须正确传递 this
onclick="delTr(this)"
如果你写成:
onclick="delTr()" // 没传 this
那函数里的 btn.parentElement
就会报错,因为 btn
是 undefined
。
❌ 限制 3:函数必须能正确找到父级 <tr>
你现在的写法:
btn.parentElement.parentElement.remove();
依赖的是固定的 DOM 结构:
<button>└── parentElement → <td>└── parentElement → <tr>
如果你以后改了结构,比如加了一层 <div>
,这个 .parentElement.parentElement
就会出错。
✅ 总结:delTr
到底能不能改?
问题 | 回答 |
---|---|
能改函数名吗? | ✅ 能!但必须同步修改 HTML 中 onclick="xxx" 的名字 |
能改函数逻辑吗? | ✅ 能!比如用 closest('tr') 更安全 |
为什么感觉不能改? | 因为 HTML 和 JS 耦合太紧,改一个忘了另一个就会报错 |
最佳实践? | 把事件绑定移到 JS 中,用 addEventListener + closest() ,完全自由可改 |
3. 第三个难点:let delTrs = document.querySelectorAll(".del") 这行代码有没有用
这行代码:
let delTrs = document.querySelectorAll(".del")
在你当前的代码中 —— 它被定义了,但并没有被使用,所以是“无效代码”或“冗余代码”。
✅ 为什么说它“没有用”?
我们来看这行代码的作用:
let delTrs = document.querySelectorAll(".del")
- 它的意思是:查找页面中所有
class="del"
的元素(也就是所有的“删除”按钮),并存入delTrs
这个变量。 - 返回的是一个 NodeList(类似数组),包含所有匹配的按钮。
👉 但是!你在后面 完全没有使用这个 delTrs
变量。
你删除行的方式是通过内联事件:
<button class="del" onclick="delTr(this)">删除</button>
也就是每个按钮自己调用 delTr(this)
函数,并不依赖 delTrs
这个列表。
所以:
✅
delTrs
被定义了
❌ 但从未被使用 → 浏览器分配了内存,但没发挥作用
📌 结论:这行代码目前是“无用的”、“可以删除的”
💡 那什么时候这行代码会有用?
如果你改用事件监听的方式来处理删除,那它就非常有用!
✅ 推荐用法:用 delTrs
给每个按钮绑定事件
你可以删除 onclick="delTr(this)"
,然后这样写:
let delTrs = document.querySelectorAll(".del");delTrs.forEach(function(button) {button.addEventListener('click', function() {this.closest('tr').remove(); // 删除所在行});
});
同时,HTML 改为:
<button class="del">删除</button> <!-- 去掉 onclick -->
✅ 这时 delTrs
就发挥了关键作用:遍历所有删除按钮,给它们绑定点击事件。
✅ 总结
问题 | 回答 |
---|---|
let delTrs = document.querySelectorAll(".del") 有没有用? | ❌ 在当前代码中没有用,因为定义了但没使用 |
可以删掉吗? | ✅ 可以安全删除,不影响功能 |
它什么时候有用? | ✅ 当你用 addEventListener 给所有删除按钮绑定事件时,它就非常有用 |
最佳实践? | 删除内联 onclick ,用 delTrs.forEach(...addEventListener) 更专业 |
✅ 建议修改(完整优化版)
// ✅ 使用 delTrs 并真正发挥它的作用
let delTrs = document.querySelectorAll(".del");delTrs.forEach(button => {button.addEventListener('click', function() {if (confirm("确定删除这一行吗?")) {this.closest('tr').remove();}});
});
这样,delTrs
就不再是“摆设”,而是核心变量了 ✅
4.3 操作方法
包扩创建元素,创建文本,创建属性,克隆节点等。
<div>盒子</div><P>段落1</P><P>段落2</P><P>段落3</P><P>段落4</P><P>段落5</P><P>段落6</P><P>段落7</P><P class="p_8">段落8</P><P>段落9</P><P>段落10</P><script>// 创建元素【重点】let div = document.createElement('div')console.log(div);// 查询元素let div_ = document.querySelector('div')console.log(div_);// 创建文本let txt = document.createTextNode('Hello')console.dir(txt);// 创建属性// div_.title ="哈哈哈"let tit = document.createAttribute('title')tit.value = '嘿嘿嘿'div_.setAttributeNode(tit)// 克隆节点let p8 = document.querySelector('.p_8')// let newP = p8.cloneNode()//浅拷贝let newP = p8.cloneNode("deep")//浅拷贝console.log(newP);div_.append(p8)</script>
4.4 插入方法
<ul><li class="list_1">内容-1</li><li class="list_2">内容-2</li><li class="list_3">内容-3</li><li class="list_4">内容-4</li><li class="list_5">内容-5</li><li class="list_6">内容-6</li><li class="list_7">内容-7</li><li class="list_8">内容-8</li><li class="list_9">内容-9</li><li class="list_10">内容-10</li></ul><script>// append()向后新增节点let li_11 = document.createElement('li')let li_1 = document.querySelector('.list_1')// 新增document.querySelector('ul').append(li_11)document.querySelector('ul').append(li_1)//如果使用的是页面现有的节点,执行的是移动的操作//可以插入字符串【但是不能解析htm1标签代码】document.querySelector('ul').append("<li>新内容</li>")// node.prepend(...nodesor strings)//在 node 开头插入document.querySelector('ul').prepend(li_11.cloneNode())// node.before(...nodes or strings)//在 node 之前插入document.querySelector('ul').before('这是before')// 在 node 之后插入// node.after(...nodes or strings)document.querySelector('ul').after('这是after')</script>
4.5 替换和移除
<h1>标题1</h1><h2>标题2</h2><h3>标题3</h3><ul><li>1</li><li>2</li><li>3</li></ul><script>// node.remove() // 移除 nodedocument.querySelector('h2').remove()// node.replaceWith(...nodes or strings) // 替换 nodelet img = document.createElement("img")img.src = "https://www.baidu.com/img/Pctm"document.querySelector('h1').replaceWith(img)</script>