事件冒泡、事件捕获及事件委托(事件代理)

直入主题,看一下代码,给它们分别绑定点击事件,观察输出>>

	<div>
			<div id="a">
				a
				<div id="b">
					b
					<div id="c">c</div>
				</div>
			</div>
		</div>

事件冒泡、事件捕获及事件委托(事件代理)

事件捕获

这里需要注意的一点:dom.addEventListener(‘eventname’,func,[boolean])
包含的三个参数:事件名称、回调函数、可选值(布尔类型)—> 该值决定事件触发以捕获的形式还是冒泡的形式,默认为false(冒泡),true(捕获)

	<script>
		var a = document.getElementById('a')
		var b = document.getElementById('b')
		var c = document.getElementById('c')
		a.addEventListener(
			'click',
			() => {
				console.log('冒泡a')
			},
			true
		)
		b.addEventListener(
			'click',
			() => {
				console.log('冒泡b')
			},
			true
		)
		c.addEventListener(
			'click',
			() => {
				console.log('冒泡c')
			},
			true
		)
	</script>

输出结果:a>b>c

事件冒泡

	<script>
		var a = document.getElementById('a')
		var b = document.getElementById('b')
		var c = document.getElementById('c')
		a.addEventListener('click', () => {
			console.log('冒泡a')
		})
		b.addEventListener('click', () => {
			console.log('冒泡b')
		})
		c.addEventListener('click', () => {
			console.log('冒泡c')
		})
	</script>

输出结果: c>b>a

事件捕获与冒泡同时注册

<script>
		var a = document.getElementById('a')
		var b = document.getElementById('b')
		var c = document.getElementById('c')
		a.addEventListener('click', () => {
			console.log('冒泡a')
		})
		b.addEventListener('click', () => {
			console.log('冒泡b')
		})
		c.addEventListener('click', () => {
			console.log('冒泡c')
		})
		a.addEventListener(
			'click',
			() => {
				console.log('冒泡a')
			},
			true
		)
		b.addEventListener(
			'click',
			() => {
				console.log('冒泡b')
			},
			true
		)
		c.addEventListener(
			'click',
			() => {
				console.log('冒泡c')
			},
			true
		)
	</script>

输出结果: a>b>c>c>b>a (先捕获再冒泡)

以上阶段分为三段:捕获阶段、目标阶段、冒泡阶段
捕获阶段:事件响应从最外层的window开始,逐层响应到内层的目标元素
目标阶段:触发事件的最底层元素
冒泡阶段:事件响应从最内层目标元素开始,一直冒泡到window
DOM事件流就是以上面的捕获阶段——目标阶段——冒泡阶段的顺序进行的
事件代理 (事件委托)就是通过事件捕获或事件冒泡的机制把一系列的内层元素事件绑定到外层元素
事件冒泡、事件捕获及事件委托(事件代理)

用代码说话——什么是事件委托以及事件委托的使用场景?

事件委托:通过事件捕获或事件冒泡机制将一系列的内层元素事件绑定到外层元素进行事件触发的过程

下面的代码要做一件事情:点击列表,将当前列的内容展示在下面的div里面

一般我们会想到的方法是,循环li,并为每个li添加点击事件,如下代码所示:

<body>
    <ul id="ul">
        <li>item1</li>
        <li>item2</li>
        <li>item3</li>
        <li>item4</li>
    </ul>
    <div id="div">
        当前被点击li中的值
    </div>
</body>
<script>
    let ul = document.getElementById('ul')
    let div =  document.getElementById('div')
    let lis = document.getElementsByTagName('li')
    console.log(lis);
    [...lis].forEach((item,index)=>{
        item.addEventListener('click',(e)=>{
            console.log(e);
            div.innerHTML = e.target.innerHTML
        })
    })
</script>

通过了解事件委托(事件代理),我们可以只为ul添加事件监听,从而通过事件捕获(事件冒泡)的机制,实现我们的需求,代码如下:

	<body>
    <ul id="ul">
        <li>item1</li>
        <li>item2</li>
        <li>item3</li>
        <li>item4</li>
    </ul>
    <div id="div">
        当前被点击li中的值
    </div>
</body>
<script>
    let ul = document.getElementById('ul')
    let div =  document.getElementById('div')
    // 事件冒泡
    ul.addEventListener('click',(e)=>{
        console.log(e.target.innerHTML);
        div.innerHTML = e.target.innerHTML
    })
    // 事件捕获
    ul.addEventListener('click',(e)=>{
        div.innerHTML = e.target.innerHTML
    },true)
</script>
上一篇:事件EventTarget接口


下一篇:Phonegap的deviceready事件