js-事件及事件委托

1. 事件

当用户浏览网页时,存在许许多多与网页交互的操作。例如按钮的点击、屏幕的滑动、鼠标的移动等等,通过这些交互完成某些操作,达到某种效果。我们可以将这些交互称之为事件。

2. 事件冒泡

事件冒泡是指事件在某个元素上触发后一直向上传播(父元素),一直传播到document。如果向上冒泡的过程中遇到相同的事件,则触发。例如下面的例子:

<body>
    <div id="myDiv">
        <ul>
            <li id="myLi">1</li>
        </ul>
    </div>
    <script>
        const li = document.getElementById('myLi')
        li.onclick = function () {
            console.log(this.id); //myLi
        }

        const div = document.getElementById('myDiv')
        div.addEventListener('click', function () {
            console.log(this.id); //myDiv
        })
    </script>
</body>

在这里插入图片描述
当我们点击li标签的时候,会触发li上绑定的click事件,但是在触发li的click事件后会触发div上绑定的click事件。这就是事件冒泡,其实仔细想想这也是可以理解的,因为点击了li标签则意味着div也被点击了。就像你住在中国的某个省,那你肯定住在中国。上面的冒泡总过程如下:

li 》ul 》 div 》body 》html 》document

3. 事件捕获

事件捕获与事件冒泡正好是个相反的过程,事件捕获会从document开始,然后一次向下传播,直到具体的元素

//dom2事件处理程序才能控制事件捕获与事件冒泡
//并且只有addEventListener的第三个参数设置为true才会是事件捕获,false是事件冒泡。
const lis = document.getElementsByTagName('li')
for (const li of lis) {
	li.addEventListener('click', () => {
		console.log('li click');
	}, true)
}

const div = document.getElementById('myDiv')
div.addEventListener('click', () => {
	console.log('div click');
}, true)

在这里插入图片描述
可以看出事件捕获与事件冒泡确实是相反的,事件捕获先执行了div的click事件,然后执行li的click事件。捕获的顺序如下

document 》html 》body 》div 》ul 》li

4. 事件模型

4.1 DOM0事件模型

DOM0事件模型比较简单,只需要将事件处理函数赋值给一个事件处理程序属性。目前的所有浏览器都支持该方式。

const div = document.getElementById('myDiv')
div.onclick = function () {
    console.log(this.id) // myDiv
}

DOM0事件模型中移除事件方式直接将事件处理程序属性的值设置为null就行

div.onclick = null
4.2 DOM2事件模型

DOM2事件模型为事件处理程序的赋值和移除定义了两个方法:addEventListener()和removeEventListener()。它们接收3个参数:事件名、事件处理函数、布尔值(默认false),true表示捕获阶段调用事件处理程序,false表示冒泡阶段调用事件处理程序。

const div = document.getElementById('myDiv')
const handler = function () {
	console.log(this.id);
}
// 绑定click事件
div.addEventListener('click', handler)

// 移除click事件
div.removeEventListener('click', handler)
// 绑定click事件
div.addEventListener('click', function () {
	console.log(this.id);
})

// 无法移除click事件
div.removeEventListener('click', function () {
	console.log(this.id);
})

tip: 传给addEventListener、removeEventListener的事件处理函数必须先赋值给一个变量,然后共同使用才能对绑定的事件进行移除,否则移除不了绑定的事件。因为在无法移除的情况下,虽然事件处理函数看起来是相同的,但是实际上是两个不同的函数,有不同的内存地址。

4.3 IE事件模型

IE事件模型为事件处理程序的赋值和移除定义了两个方法:attachEvent()和attachEvent()。它们接收2个参数:事件名、事件处理函数。因为 IE8 及更早版本只支持事件冒泡,所以使用 attachEvent()添加的事件处理程序会添加到冒泡阶段。

const div = document.getElementById('myDiv')
const handler = function () {
	console.log(this.id);
}

//添加点击事件,注意是onClick
div.attachEvent("onclick", handler);

//移除事件
div.detachEvent("onclick", handler);
4.4 3种事件模型的其他事项

DOM0事件中this指向当前元素

DOM0事件中为同一个元素赋值两次onclick,后面会覆盖前面的(因为是赋值)

DOM2事件中this指向当前元素

DOM2可以通过addEventListener为同一个元素添加多个事件函数,并且顺序执行(观察者模式)

IE事件模型中事件处理程序是在全局作用域中运行的,因此 this 等于 window

IE事件模型可以通过attachEvent为同一个元素添加多个事件函数,但是是逆序执行的,即先添加的最后执行

5. 事件委托

事件委托又称为事件代理,事件委托就是将原本绑定到子元素的事件委托给父元素。在开发中最常见的就是菜单栏由ul和多个子li标签组成。如果要为菜单栏添加点击事件,通常方法是直接在li上绑定对应的点击事件。但是这样不利于未来添加其他的菜单项,即所谓的可扩展性。而且为每个li添加事件是费时费力的。所以通常解决办法是利用事件冒泡的特性,将事件绑定到ul标签上。

通俗的例子就是寝室中,本来是每个人都要去取快递的,但是一想这样太浪费人力了,所以非常民主地选择寝室长一个人去,一起代领。

下面看下实际的例子:

<body>
    <ul id="myUl">
        <li>1</li>
        <li>2</li>
        <li>3</li>
    </ul>
    <script>
        //事件委托实现
        const ul = document.getElementById('myUl')
        ul.onclick = function (e) {
            console.log(e.target.innerHTML);
        }

		//事件委托的等效代码:为每个li添加事件,
        const lis = document.getElementsByTagName('li')
        for (const li of lis) {
            li.onclick = function () {
                console.log(this.innerHTML);
            }
        }
    </script>
</body>

在这里插入图片描述
事件委托可以通过从事件对象的target属性中获取点击的目标,可以看出使用事件委托,只需要在父元素上绑定所需的事件。而通过一般的事件绑定则需要为每个子元素绑定事件。

事件委托的优势:

通过使用事件委托不需要为每个子元素设置事件函数,可以减少页面所需的内存,提升页面的整体性能;实现事件的动态绑定,新增节点不必单独添加监听事件,发生的事件交给父元素。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值