DOM(四):注册和删除事件、DOM事件流、事件对象、事件委托

一、注册事件和删除事件:传统or方法监听

1.注册事件的两种方式

<button>传统注册方式</button>
<button>方法监听注册事件</button>

第一种:传统注册事件也就是我们之前常用的

var btn = document.querySelectorAll('button');
//传统注册事件
btn[0].onclick = function () {
    alert('hi');
}

第二种:方法监听注册事件
语法是下面这样,注意事件类型onclick一定要去掉on

btn[1].addEventListener('click', function () {
    alert('aoaoao'); 
})

二者的区别:传统方法同一个元素只能添加一个监听器,如果添加多个会被覆盖;第二种方法同一个元素,同一个事件可以添加多个监听器(function里面的东西就叫监听器)

2.删除事件的两种方式

比如有两个div

<div>传统注册方式</div>
<div>方法监听注册事件</div>

第一种:传统注册事件删除事件用this.onclick = null;

var div = document.querySelectorAll('div');
div[0].onclick = function () {
    alert('11');
    //删除事件实现点击一次就失效
    this.onclick = null;
}

第二种:方法监听注册事件删除事件用this.removeEventListener(‘click’, fn);
其中fn是函数的名字,这里注意不要写fn(),语法规定只写函数名字,不调用
点击一次之后就删除事件

div[1].addEventListener('click', fn);
function fn() {
    alert('22');
    div[1].removeEventListener('click', fn);
}

二、DOM事件流

事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程即DOM事件流
事件捕获阶段→处于目标阶段→事件冒泡阶段
在这里插入图片描述
代码验证:
上面讲的方法监听注册事件,实际上还有第三个参数,这个参数就是决定是事件捕获还是事件冒泡
比如我来两个div:

	<div class="father">
	    <div class="son">son</div>
	</div>

如果第三个参数是true,那么就是事件捕获,从上往下捕获,这个时候我如果点son,会先弹出来father,再弹出来son,如果我点father,只弹出来father(看上面的图,因为点击father只捕获到father)

	var father = document.querySelector('.father');
	var son = document.querySelector('.son');
	//给父亲添加点击事件,true表示事件捕获
	father.addEventListener('click', function () {
	    alert('father');
	}, true);
	//点击son,结果弹出来father,再弹出来son
	son.addEventListener('click', function () {
	    alert('son');
	}, true);

如果第三个参数是false或者不写,那么就是事件冒泡,从下往上冒泡,这个时候我如果点son,会先弹出来son,再弹出来father。点击father,只弹father,为什么不是先son再father?因为和捕获不一样,冒泡是从当前执行的地方往上冒,不会去找儿子。这个地方再看可能有点看不懂……不过问题不大,看图说话。

   var father = document.querySelector('.father');
    var son = document.querySelector('.son');
    //给父亲添加点击事件,true表示事件捕获,false或者不写表示事件冒泡
    father.addEventListener('click', function () {
        alert('father');
    }, false);
    //点击son,结果弹出来son,再弹出来father
    son.addEventListener('click', function () {
        alert('son');
    }, false);

一般冒泡用的多一点,如果父节点true捕获,子节点不管是false冒泡还是true捕获,那么点击子节点都是先father再son。这是因为事件流的顺序是事件捕获阶段→处于目标阶段→事件冒泡阶段,捕获阶段先执行,如果father是捕获就先弹father,这时候son其实就是目标阶段,son是冒泡还是捕获已经不重要了。而如果father是冒泡,那么捕获阶段走过来不会执行father,走完son再往上走,才能找到father,所以会先son再father。所以主要要看father是什么

三、事件对象

1.什么是事件对象?

说实话这个地方听的有点云里雾里,先截个图
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

2.事件对象常用的属性和方法

在这里插入图片描述

(1)event.target返回触发事件的对象(元素)

比如有个ul

<ul>
    <li>111</li>
    <li>222</li>
    <li>333</li>
</ul>

target属性和this的区别是什么呢?
event.target返回的是触发事件的对象(元素),而this返回的是绑定事件的对象(元素)
.target是点了谁就返回谁,比如下面这个我绑定的是ul,那我点击li触发了ul,那么.target返回的就是li。而this则返回的是我绑定的ul

var ul = document.querySelector('ul');
ul.addEventListener('click', function (event) {
    console.log(this);  //返回ul
    console.log(event.target);  // 返回li
    console.log(event.type);  //返回click
})

(2)event.preventDefault() 阻止默认行为

比如这样的a标签

   <a href="http://www.baidu.com">链接</a>

我点击之后会自动跳到百度,是默认的
但是如果我在a的点击事件里加了这样一句话

	//阻止默认事件event.preventDeafult();
	var a = document.querySelector('a');
	a.addEventListener('click', stop);
	function stop(e) {
	    e.preventDefault();
	}

点击就跳转不鸟了
传统注册事件也是一样的代码,考虑兼容问题用return false,但是return false后面的代码就不执行了,不太好

(3)event.stopPropagation() 阻止事件冒泡

比如二、DOM事件流中我们提到的冒泡案例,点击son,father也会执行。但是如果我在son里加了事件对象e并添加了e.stopPropagation() ;就不会继续往上冒了,点击son只弹son。简单来说就是加了这句话,冒泡到son这里,嘎,就停了

   var father = document.querySelector('.father');
    var son = document.querySelector('.son');
    //给父亲添加点击事件,true表示事件捕获,false或者不写表示事件冒泡
    father.addEventListener('click', function () {
        alert('father');
    }, false);
    //点击son,结果弹出来son,再弹出来father
    son.addEventListener('click', function () {
        alert('son');
        e.stopPropagation(); //阻止事件冒泡
    }, false);

四、事件委托(重点理解)

原理:不在每个子节点单独设置事件监听器(函数),而是在其父节点上设置事件监听器,然后利用事件冒泡来通过子节点影响父节点
比如有这样的ul和li

<ul>
    <li>惊起一滩鸥鹭</li>
    <li>惊起一滩鸥鹭</li>
    <li>惊起一滩鸥鹭</li>
    <li>惊起一滩鸥鹭</li>
    <li>惊起一滩鸥鹭</li>
</ul>

如果想点击每个li就变色,那么按照以前的方式,我们要循环给每个li添加注册事件,但这样非常麻烦,而且如果添加的太多会影响页面效率。那么我们可以给li的父节点ul添加点击事件,然后当我们点击li时,事件会冒泡到ul上,从而触发ul的事件监听器,这时候如果我们想对li操作,可以利用事件对象的target属性找到它

var ul = document.querySelector('ul');
ul.addEventListener('click', function (e) {
    e.target.style.backgroundColor = 'pink';
})

五、常用的键盘鼠标事件

1、鼠标事件

(1)常用的鼠标事件

在这里插入图片描述

(2)鼠标事件对象

在这里插入图片描述

2、键盘事件对象

(1)常用的键盘事件

三个事件的执行顺序:keydown→keypress→keyup
在这里插入图片描述

(2)键盘事件对象

不过弹幕说keyCode已经被弃用了,现在直接.key就可以直接返回按的哪个键
在这里插入图片描述

(3)案例:按下s键获取文本框焦点

var search = document.querySelector('input');
document.addEventListener('keyup', function (e) {
    if (e.key == 's' || 'S') {
        search.focus();
    }
})

(4)案例:京东快递单号查询

按照惯例,先上html和css

.box {
    position: relative;
    margin: 100px 100px;
}

.big {
    position: absolute;
    display: none;
    top: -62px;
    height: 50px;
    border: 1px solid black;
    font-size: 30px;
}

.big::before {
    /* 当父元素不需要占有位置时,子绝父绝也是可以的 */
    position: absolute;
    left: 10px;
    bottom: -21px;
    content: '';
    display: inline-block;
    width: 0;
    height: 0;
    border: 10px solid transparent;
    border-top-color: black;
}
<div class="box">
    <div class="big"></div>
    <input type="text" placeholder='请输入你的快递单号:'>
</div>

其实这个案例还是比较简单的,这里注意要用keyup,键盘抬起触发,要是用keydown或者keypress会有bug,比如keydown的话是按下先执行监听器,然后才填内容,也就是会有一个小小的延迟。

   var big = document.querySelector('.big');
    var input = document.querySelector('input');
    input.addEventListener('keyup', function (e) {
        if (input.value != '') {
            big.innerHTML = this.value;
            big.style.display = 'block';
        } else {
            big.style.display = 'none';
        }

    })

    //离开焦点隐藏
    input.addEventListener('blur', function () {
        big.style.display = 'none';
    })

    //获得焦点时,如果文本框内容不为空,就显示放大
    input.addEventListener('focus', function () {
        if (input.value != '') {
            big.style.display = 'block';
        }
    })
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值