1. DOM0事件绑定和解绑
- DOM0高级浏览器中同一个对象 绑定同一个事件 那么会覆盖
- DOM0事件解绑 本质上就是把事件回调函数和事件对象的事件属性断开指向
box.onclick= null
2. Dom2事件绑定和解绑
前提:DOM2事件添加和解绑高低浏览器使用的方法是不同的
-
高级浏览器
- 添加事件监听1
(1)添加事件监听类型
(2)回调函数
- 添加事件监听1
box.addEventListener('click',function(){
console.log('老马去红浪漫');
});
- DOM2高级浏览器 同一个对象绑定同一个事件的执行顺序是从上到下依次执行的
- 添加事件监听方法2 (函数定义在外边以便变量来调用 )
function fn(){
console.log('马斯托洛夫斯基');
}
box.addEventListener('click',fn);
function fn1(){
console.log('马坚强');
}
box.addEventListener('click',fn1);
- Dom2事件的解绑
- DOM2事件解绑的时候,参数必须和绑定的时候一模一样
- 如果DOM2事件要解绑,那么就不能在方法内部去定义回调函数,必须添加的时候在外部定义有名函数
btn.onclick = function(){
box.removeEventListener('click',function(){
console.log('布鲁斯马!');
});
} //解绑不了,因为回调函数和绑定的虽然看着一样,但是不是同一个函数
function fn(){
console.log('杰森斯坦马');
}
box.addEventListener('click',fn);
btn.onclick = function(){
box.removeEventListener('click',fn);
}
-
低级浏览器
- 添加事件监听1
//低级浏览器
//添加事件监听
box.attachEvent('onclick',function(){
console.log('哈哈');
})
- 如果添加多个事件,那么也会依次执行,只不过执行顺序和高级浏览器相反
- 添加事件监听2
function fn1(){
console.log('嘿嘿');
}
box.attachEvent('onclick',fn1);
- 解绑方式
function fn1(){
console.log('嘿嘿');
}
box.attachEvent('onclick',fn1);
btn.onclick = function(){
box.detachEvent('onclick',fn1);
}
DOM0和DOM2.jpg
3. 事件流
3.1 DOM0事件的事件流(默认冒泡)
- Dom0事件的事件流都是冒泡,没有捕获
- 整体事件流会由最里层---子元素---父元素---body---html---document---window
- DOM0事件取消冒泡的三种方法(高级浏览器)
- 方法1
event.cancelBubble = true;
- 方法2
event.stopPropagation();
- 方法3
event.stopImmediatePropagation();
- 方法1
- DOM0事件低级浏览器中取消冒泡方法
-
只有这个方法可以取消冒泡
event.cancelBubble = true;
低级浏览器的event对象中没有stopPropagation
低级浏览器的event对象中没有stopImmediatePropagation
- event高级浏览器可以直接使用
低级浏览器中的事件对象是window.event
兼容性写法:event = event || window.event;
-
只有这个方法可以取消冒泡
3.2 DOM2事件的事件流(默认冒泡)
-
DOM2高级浏览器
- DOM2整体事件流会由最里层---子元素---父元素---body---html---document---window
- DOM2事件取消冒泡的三种方法(高级浏览器)
- 方法1
event.cancelBubble = true;
- 方法2
event.stopPropagation();
- 方法3
event.stopImmediatePropagation();
- 方法1
- DOM2事件-捕获事件流接收第三个参数
true
- 捕获整体事件流会由最外层---window---document----html---body---父元素---子元素
- 取消捕获事件以上三种方法均可 一般使用的是
event.stopImmediatePropagation();
-
DOM2低级浏览器
- DOM2整体事件流会由最里层---子元素---父元素---body---html---document---window
- DOM2的低级浏览器 可以直接使用event对象
取消冒泡只有一种event.cancelBubble = true;
总结:DOM0事件及低级浏览器的DOM2事件(没有第三个参数)都是只有冒泡,以后用的最多的也是冒泡,捕获几乎不用,高级浏览器的DOM2事件可以根据第三个参数选择是捕获还是冒泡,一般都不写,默认是冒泡
4. 事件委派
4.1 什么是事件委派
- 事件委派过程当中依赖了事件冒泡
- 事件冒泡的好处就是可以进行事件委派(事件委托,事件代理);
- 把子元素的事件监听添加给父(祖先)元素,把子元素发生的事件委托给父元素进行处理
4.2 事件委派用法
- 使用事件委派的情况有且仅有2种
-
1:当新添加的对象 想要具备老的对象的方法的时候, 此时就想事件委派;不用事件委派,老对象身上会有想要的行为,而新添加的没有
-
2:当对象很多 并且每一个对象都绑定了相同的事件对象的时候
因为内存浪费的问题 所以要使用事件委派
-
- 事件委派的作用:可以大大降低内存的占用,并且可以提高效率。
总结 :
事件委派其实是借用事件冒泡去做的,因为事件冒泡导致内部所有的元素发生事件都会冒泡到祖先身上,我们不在子元素身上去添加事件监听和处理,而是在共同的祖先身上去添加,让祖先去处理子元素发生的事件;祖先去处理其实就是通过事件对象当中的target 去获取到真正发生事件的子元素;对子元素进行处理
可以通过事件对象的target属性来找到你真实操作的那个标签
通过target的nodeName就知道我移入的是哪个标签(大写标签 eg: UL/LI/SPAN)
- 案例练习 --- 新添加对象具备老对象属性
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>事件委派-为什么要学习事件委派</title>
</head>
<body>
<ul>
<li>红酒搓</li>
<li>牛奶搓</li>
<li>醋搓</li>
<li>辣椒搓</li>
</ul>
<button>添加</button>
<script>
var btn = document.querySelector('button');
var ul = document.querySelector('ul');
// 点击按钮之后给ul添加li
btn.onclick = function(){
var li = document.createElement('li');
li.innerHTML = '搓搓搓';
ul.append(li);
}
ul.onmouseover = function(event){
if(event.target.nodeName == 'LI'){
event.target.style.backgroundColor = 'skyblue';
}
}
ul.onmouseout = function(event){
if(event.target.nodeName == 'LI'){
event.target.style.backgroundColor = '';
}
}
// 高亮
// 注意 今天我们使用的移入移出 是onmouseover onmousepout
// var li_list =document.querySelectorAll('li');
// console.log(li_list.length);
// for(var i = 0; i < li_list.length; i++){
// li_list[i].onmouseover = function(){
// this.style.backgroundColor = 'yellowgreen';
// }
// li_list[i].onmouseout = function(){
// this.style.backgroundColor = '';
// }
// }
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>事件委派-移入的标签的内部还有标签</title>
</head>
<body>
<ul>
<li>麻婆豆腐</li>
<li>青椒皮蛋</li>
<li>蒜苗回锅肉</li>
<li>
<span>香菜牛肉</span>
</li>
</ul>
<script>
var ul = document.querySelector('ul');
ul.onmouseover = function(event){
if(event.target.nodeName == 'LI'){
event.target.style.backgroundColor = 'skyblue';
}else if(event.target.parentElement.nodeName == 'LI'){
event.target.parentElement.style.backgroundColor = 'skyblue';
}
}
ul.onmouseout = function(event){
if(event.target.nodeName == 'LI'){
event.target.style.backgroundColor = '';
}else if(event.target.parentElement.nodeName == 'LI'){
event.target.parentElement.style.backgroundColor = '';
}
}
</script>
</body>
</html>
5. 两对移入移出区别
-
onmouseover/onmouseout
如果涉及到事件切换或者冒泡必须使用双o如果是一个父子元素模型,对父元素添加移入和移出,当鼠标移入父元素里面的子元素的时候,事件会移出然后再移入。也就是说事件元素会有切换;事件委派的时候,必须使用这一对,大部分的时候我们使用的事件流都是冒泡,冒泡一定会涉及到事件的切换,所以我们常用双o事件;
-
onmouseenter/onmouseleave
如果是一个父子元素模型,对父元素添加移入和移出,当鼠标移入父元素里面的子元素的时候,
事件并没有移出然后再移入。也就是说事件元素没有切换; -
企业级开发中大部分使用的是onmouseenter/onmouseleave 因为不会发生事件切换 不会影响动态效果
使用双o在部分浏览器下会发生卡顿现象。如果使用冒泡必须使用双o
- 案例练习 --- 表格的增删改查
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>13_作业</title>
<style>
.container {
width: 800px;
height: 500px;
border: 1px solid #000;
margin: 50px auto;
padding: 15px;
}
table {
table-layout: fixed;
text-align: center;
table-layout: fixed;
border-collapse: collapse;
width: 600px;
margin: 30px auto;
}
</style>
</head>
<body>
<div class="container">
<!-- <form action="#"> -->
<label> 姓名: <input type="text" id="name"/> </label>
<label> 年龄: <input type="text" id="age"/> </label>
<label> 性别: <input type="text" id="gender"/> </label>
<button id="btn">添加</button>
<!-- </form> -->
<table border="1">
<tr>
<th>姓名</th>
<th>年龄</th>
<th>性别</th>
<th>操作</th>
</tr>
<tr>
<td>马大</td>
<td>18</td>
<td>男</td>
<td>
<a href="#">删除</a>
</td>
</tr>
<tr>
<td>马二</td>
<td>16</td>
<td>男</td>
<td>
<a href="#">删除</a>
</td>
</tr>
</table>
</div>
<script>
var addBtn = document.querySelector('#btn')
var tableTbody = document.querySelector('table tbody')
addBtn.addEventListener('click', function() {
// (1) 获取文本框中的内容
var input = document.querySelectorAll('input')
// name
var nameVal = input[0].value
// age
var ageVal = input[1].value
// gender
var genderVal = input[2].value
var tr = document.createElement('tr')
var td_name = document.createElement('td')
td_name.innerHTML = nameVal
tr.append(td_name)
var td_age = document.createElement('td')
td_age.innerHTML = ageVal
tr.append(td_age)
var td_gender = document.createElement('td')
td_gender.innerHTML = genderVal
tr.append(td_gender)
// 有bug 超链接没有小手 因为没有href
// var a = document.createElement('a');
// // a.href = '#';
// a.innerHTML = '删除';
// var td = document.createElement('td');
// td.append(a);
// tr.append(td);
var td_del = document.createElement('td')
td_del.innerHTML = '<a href="#">删除</a>'
tr.append(td_del)
tableTbody.append(tr)
})
// 老对象可以实现 新增对象不生效 无法删除 需要事件委派
// var a_list = document.querySelectorAll('a');
// for(var i = 0; i < a_list.length; i++){
// a_list[i].onclick = function(){
// this.parentElement.parentElement.remove();
// }
// }
tableTbody.onclick = function(event) {
if (event.target.nodeName == 'A') {
var flag = confirm('你确定要删除嘛?')
if (flag) {
event.target.parentElement.parentElement.remove()
}
}
}
</script>
</body>
</html>
网友评论