事件冒泡:
子元素嵌套在父元素内部,点击子元素的时候一定同时表示点击了父元素,这个时候,先触发子元素的事件处理器,然后再触发父元素的事件处理器,如果父元素的父元素还有处理器,就一直向上触发,一直到 html > document 元素。就像鱼吐泡泡一样,从水下向水面走,每向上走一层就会查看这一层有没有事件处理器,如果有的话就会触发,如果没有的话就继续向上寻找,直到顶层的html > document ,才结束寻找事件。
事件捕获:
事件捕获则和事件冒泡正好相反,点击的时候从 window > document > html > body > 往下找,如果父级元素有事件处理器就先触发父级元素的事件处理器,再向下一层,如果子级元素有的话就触发子级元素的事件处理器,直到这个点击位置的最底层,也就是我们通常所说的 target。事件捕获就好像一块石头从水面向水下沉一样,如果这一层有事件处理器,就触发,没有就继续向下沉,到下层再查看是否有事件处理器,有的话就触发,没有的话继续向下,一直到最底层,这个石头就停止了。
理论说完了 我们测试下说个小案例吧。
HTML结构
下来js绑定冒泡事件document.getElementById("parent").addEventListener("click",function(e){
alert("parent事件被触发,"+this.id);
})
document.getElementById("child").addEventListener("click",function(e){
alert("child事件被触发,"+this.id)
})
结果:
child事件被触发,child
parent事件被触发,parent
结论:先child,然后parent。事件的触发顺序自内向外,这就是事件冒泡。
下来我们测试捕获 现在改变第三个参数的值为truedocument.getElementById("parent").addEventListener("click",function(e){
alert("parent事件被触发,"+e.target.id);
},true)
document.getElementById("child").addEventListener("click",function(e){
alert("child事件被触发,"+e.target.id)
},true)
结果:
parent事件被触发,parent
child事件被触发,child
结论:先parent,然后child。事件触发顺序变更为自外向内,这就是事件捕获。
捕获实际中应用比较少~
===============一条朴素的分割线====================
通过事件冒泡做的留言本
来上代码可以预览哦。
实例
html>
7.11 留言板-大灰狼*{margin: 0;padding: 0;}
body{
background:#000000 url(https://inews.gtimg.com/newsapp_match/0/49787475/0) no-repeat;
background-size:100%; color:green; position: relative;}
.guestbook{width: 800px;
min-width: 800px;
font-family: "微软雅黑";
font-weight: bold;
position: fixed;
left: 10%;
bottom: 15px;}
#list{list-style: none;}
#list li{background: skyblue;
opacity: 0.6;
border:1px solid slateblue;
border-radius: 5px;
min-heightheight: 30px;
margin: 10px 0;
padding: 5px;}
#list li button{float: right;
background:darkcyan;
color: #ffffff;
border: 0;
padding: 3px;
border-radius: 5px;
}
#name,
#message{border-radius: 8px; border: 0;line-height: 26px;margin: 10px; padding: 6px;}
#message{width: 300px;}
您的称呼:
发表留言:
//获取消息框input输入框
var message=document.getElementById("message");
//准备插入子元素的 留言列表
var list=document.getElementById("list");
//产生一个随机数
var rnum=Math.round(Math.random()*10);
document.getElementById("name").value="游客"+rnum;
//给input输入框添加事件监听 键盘事件 冒泡
message.addEventListener('keypress',addMessage,false);
//addMessage事件方法
function addMessage (ev) {
//事件方法中有一个默认的参数 就是事件对象:ev,evt,event 任选一个都一样
//使用ev.key 可以获取到 某一个按键的对应值
//发言昵称
var names=document.getElementById("name").value;
//发言时间
var addtime=new Date().toLocaleString();
//console.log(ev.key);
//当按下回车进行操作 并且不等于空
if(ev.key==="Enter" && message.value!="" && names.value!=""){
//要把input插入到留言列表就先要把input的文本放到一个元素比如li
//所以要先创建li元素
var liTemp=document.createElement("li");
//创建的li是空的 给里面插入input输入的文本
liTemp.innerHTML=names+' : '+message.value+ ' --发表于:' +addtime +" 删除";
//留言数据已经准备好了 来插入到留言列表里面吧
//list.appendChild(liTemp); //留言升序排列
//我们来做一个判断 进行降序插入留言(最新留言在最上面)
if (list.childElementCount===0) {
//当ul列表子元素为0个直接插入
list.appendChild(liTemp);
} else{
//如果有留言插入到第一条留言前面
//insertBefore(a,b) 有2个参数a插入的元素 b插入的位置
//list.insertBefore(liTemp,list.firstElementChild); //将新发言从前面插入
list.appendChild(liTemp); //将消息从后面插入
}
//插入成功后 我们把输入框清空 message.value=""
message.value=null;
}
}
//给留言列表的button删除按钮添加监听事件
list.addEventListener('click',messageDel);
//messageDel函数
function messageDel (ev) {
//currentTarget 事件属性返回其监听器触发事件的节点,即当前处理该事件的元素、文档或窗口。
//是 ul。currentTarget是把事件添加给谁了
//var ul=ev.currentTarget;
//是li 。target正在触发事件的元素
//var but=ev.target;
//判断点击的是button 还是li
if (event.target.nodeName=="BUTTON") {
//消息删除弹窗询问
if(confirm("是否确定要删掉?")){
//当前正在出发事件的元素,正在被点击的。
// 当前拿到的是button按钮 我们要删除li 是他的父节点
//console.log(ev.target);
//var li=but.parentElement;
//console.log(li)
//进行删除
ev.currentTarget.removeChild(ev.target.parentElement);
}
}
}
7.13日进行了更新 发现上一个版本布局兼容有问题。
运行实例 »
点击 "运行实例" 按钮查看在线实例
也可以通过以下网址 访问小案例 源码注解比较详细