事件委托:e.target
核心:1.通过事件冒泡给子元素添加事件,控制新生成的元素进行操作
2.减少DOM元素操作,只需要绑定一个父元素就可以,不用循环遍历每一个子元素进行绑定事件操作,提高程序性能
目的:给所有元素(包括新生成的)进行修改删除操作
事件监听:addEventListener 清除 removeListener(定义事件的变量名)
作用:给同一个对象绑定多个相同事件 (二级事件)
不使用事件监听后面绑定的相同事件会覆盖前面的事件(0级事件)
<button id="btn">最前插入新节点</button>
<button id="btn2">最后插入新节点</button>
<ul id="uu">
<li>桃园豪杰三结义 <button class="rep">替换</button> <button class="del">删除</button></li>
<li>孙坚跨江击刘表 <button class="rep">替换</button> <button class="del">删除</button></li>
<li>吕奉先射戟辕门 <button class="rep">替换</button> <button class="del">删除</button></li>
<li>关公赚城斩车胄 <button class="rep">替换</button> <button class="del">删除</button></li>
<li>玄德荆州依刘表 <button class="rep">替换</button> <button class="del">删除</button></li>
<li>赵子龙单骑救主 <button class="rep">替换</button> <button class="del">删除</button></li>
<li>诸葛亮痛哭庞统 <button class="rep">替换</button> <button class="del">删除</button></li>
<li>关云长败走麦城 <button class="rep">替换</button> <button class="del">删除</button></li>
<li>武侯弹琴退仲达 <button class="rep">替换</button> <button class="del">删除</button></li>
<li>魏主政归司马氏 <button class="rep">替换</button> <button class="del">删除</button></li>
</ul>
<script>
//获取元素
// 前面添加按钮
var btn1 = document.getElementById("btn")
// 后面添加按钮
var btn2 = document.getElementById("btn2")
// 父元素
var ul = document.getElementById("uu")
//绑定点击添加事件
// 前面添加
btn1.onclick = function () {
var li = document.createElement("li")
li.innerHTML = `桃园三结义前传 <button class="rep">替换</button> <button class="del">删除</button>`
ul.insertBefore(li, ul.children[0])
}
// 后面添加
btn2.onclick = function () {
var li = document.createElement("li")
li.innerHTML = `司马氏崛起后传 <button class="rep">替换</button> <button class="del">删除</button>`
ul.appendChild(li)
}
使用addEventListener事件委托
// 替换
ul.addEventListener("click", function (event) {
var target = event.target
console.log(target.innerHTML);
💨核心://判断点击的是替换还是删除按钮
if (target.innerHTML == "替换") {
//创建元素
var li = document.createElement("li")
//给元素添加内容
li.innerHTML = `删减修改后版本 <button class="rep">替换</button> <button class="del">删除</button>`
//替换节点
ul.replaceChild(li, target.parentElement)
} else {
// 删除
if (confirm("你确认要删除这一条信息吗?")) {
//通过父元素删除节点
ul.removeChild(target.parentElement)
}
}
})
</script>
注意:innerHTML和innerText是属性,不加小括号 console.log( target.innerText) 直接获取
bug心得:在实现修改和删除功能中,我是给ul分两次绑定点击事件,想分布实现修改和删除,然后发现不管是点击修改还是删除都只执行上面一种代码,然后经过指导做if判断点击的是那个按钮来分别实现不同的功能
动态修改:上面的是替换一个死的li标签,我们希望通过点击修改然后弹出输入框输入自定义的内容进行修改
重点:给父元素添加的事件委托里面所有的不同事件都可以通过冒泡事件呈现
注意:只有同类型的才可以
比如双击可以冒泡单击 单击可以冒泡失焦
单击不能冒泡双击,移入移出
总结: 冒泡情况有很多种,具体的还需要实践 主要分享不是要一样的事件才可以冒泡
// 事件委托进行修改和删除
ul.addEventListener("click", function (e) {
var target = e.target
if (target.innerText == "替换") {
var input = document.createElement("input")
input.autofocus = true//添加自动聚焦提高用户体验
ul.replaceChild(input, target.parentElement)
//失焦事件 鼠标移出触发
input.onblur = function () {
if (confirm("你确认要修改这一条内容吗?")) {//判断是否确认修改/防止误触
if (input.value) {//判断内容是否有修改的内容
// 如果修改就把值给新的li
console.log(input.value);
var li = document.createElement("li")
li.innerHTML = `${input.value}<button class="rep">替换</button> <button class="del">删除</button>`
ul.replaceChild(li, input)
} else {
alert("修改内容不能为空!")
// // 如果没有修改就返回之前的li标签
ul.replaceChild(target.parentElement, input)
}
} else {
// 如果没有修改就返回之前的li标签
ul.replaceChild(target.parentElement, input)
}
}
} else if (target.innerText == "删除") {//判断是否确认删除/防止误触
if (confirm("确认要删除这一条吗?")) {
ul.removeChild(target.parentElement)
}
}
})
多次进行if判断的目的就是优化逻辑 防止用户多种操作出现bog
可以通过nodeName className innerText 来判断是不是删除按钮
最终版:解决了点击修改之后可以点击其他按钮的操作 添加了禁用其他按钮操作
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
li {
margin-bottom: 3px;
}
</style>
</head>
<body>
<button id="btn">最后插入新节点</button>
<ul id="uu">
<li>桃园豪杰三结义 <button class="rep">替换</button> <button class="del">删除</button></li>
<li>孙坚跨江击刘表 <button class="rep">替换</button> <button class="del">删除</button></li>
<li>吕奉先射戟辕门 <button class="rep">替换</button> <button class="del">删除</button></li>
<li>关公赚城斩车胄 <button class="rep">替换</button> <button class="del">删除</button></li>
<li>玄德荆州依刘表 <button class="rep">替换</button> <button class="del">删除</button></li>
<li>赵子龙单骑救主 <button class="rep">替换</button> <button class="del">删除</button></li>
<li>诸葛亮痛哭庞统 <button class="rep">替换</button> <button class="del">删除</button></li>
<li>关云长败走麦城 <button class="rep">替换</button> <button class="del">删除</button></li>
<li>武侯弹琴退仲达 <button class="rep">替换</button> <button class="del">删除</button></li>
<li>魏主政归司马氏 <button class="rep">替换</button> <button class="del">删除</button></li>
</ul>
<script>
var ul = document.querySelector("ul")
var btn = document.getElementById("btn")
var num = 0
// 修改的时候禁用替换和删除
var btn1 = document.getElementsByClassName("rep")
var btn2 = document.getElementsByClassName("del")
var lis = document.querySelectorAll("li")
// console.log(lis.length);
// 创建空格节点 这里没有用空格节点 直接在两个按钮中间打的空格
// var text = document.createTextNode("")
// 添加
btn.onclick = function () {
num++
ul.innerHTML += `<li><span>司马氏执政后${num}</span><button class="rep">替换</button> <button class="del">删除</button></li>`
fun()
}
//修改删除
ul.addEventListener("click", function (e) {
// 兼容
var target = e.target || window.event.target
if (target.innerText == "删除") {
if (confirm("确认删除吗?")) {
this.removeChild(target.parentElement)
}
} else if (target.innerText == "替换") {
// 这里不能使用var来定义 下面那个函数获取不到 如果没有替换还需要还原这个标签
targets = target.parentElement
// console.log(targets);//当前被替换的内容
var li = document.createElement("li")
var input = document.createElement("input")
input.autofocus = true //聚焦输入框
input.style.width = "105px"
li.appendChild(input)
li.innerHTML += ` <button>确认</button> <button>取消</button>`
ul.replaceChild(li, target.parentElement)
// 在修改的时候重新获取一次li的个数
lis = document.querySelectorAll("li")
console.log(lis.length);
fun()
//禁用
dist()
}
})
// 点击替换之后判断是否确认替换
ul.addEventListener("click", function (e) {
// 获取新创建的input标签 在点击确认的时候进行非空判断
var input = document.querySelector("input")//这里要再获取一次才可以拿到这个标签才可以获取输入的值
// 兼容
var target = e.target || window.event.target
if (target.innerText == "确认") {
var text = input.value
// console.log(text);
if (text) {//非空判断
var li = document.createElement("li")
li.innerHTML += `<span>${text}</span><button class="rep">替换</button> <button class="del">删除</button>`
ul.replaceChild(li, target.parentElement)
fun()
disf()
} else {
alert("内容不能为空!")
ul.replaceChild(targets, target.parentElement)
disf()
}
} else if (target.innerText == "取消") {
ul.replaceChild(targets, target.parentElement)
disf()
}
})
// /* 使用一个盒子来包文字内容的宽 方便适应不同的文字长度破坏整体美观性 */
function fun() {
var span = document.querySelectorAll("span")
for (var i = 0; i < span.length; i++) {
span[i].style.display = "inline-block"
span[i].style.width = "117px"
span[i].style.whiteSpace = "nowrap"
span[i].style.overflow = "hidden"
span[i].style.textOverflow = "ellipsis"
}
}
//禁用
function dist() {
btn.disabled = true
//因为替换的时候那一个li没有删除按钮所以少一个//但是要在点击修改之后重新获取一次li的个数
for (var i = 0; i < lis.length - 1; i++) {
btn1[i].disabled = true
btn2[i].disabled = true
}
}
//解除禁用
function disf() {
btn.disabled = false
for (var i = 0; i < lis.length; i++) {
btn1[i].disabled = false
btn2[i].disabled = false
}
}
</script>
</body>
</html>
下面不用看了^-^
以下是错误代码展示
// 替换
ul.addEventListener("click", function (event) {
var target = event.target
var li = document.createElement("li")
li.innerHTML = `删减修改后版本 <button class="rep">替换</button> <button class="del">删除</button>`
ul.replaceChild(li, target.parentElement)
})
//删除
ul.addEventListener("click", function (event) {
var target = event.target
ul.removeChild(target.parentElement)
})
这样无论点击修改还是删除都只执行修改程序
因为没有给点击做判断是修改还是删除就默认执行上面的程序