先导
- 关于冒泡
- 关于如果取消滚动事件冒泡
- 关于事件委托
- 关于自定义事件
关于冒泡
首先在探讨冒泡之前我们应该先创建一个场景
<div class="grandpa" >
<div class= "father">
<div class= "son">
文字
</div>
</div>
</div>
在此场景中有祖先元素,父元素,有子元素我们同时为三个元素添加不同的监听点击事件
当点击文字时,是否会出现全部事件被触发的情况,又或者是仅触发文字所在的事件?
结果是算是全部触发,但是又有一个问题需要探讨,当点击文字时是外层的监听事件先触发,还是里层的监听事件先触发呢?
在W3C的标准中,规定浏览器应该同时支持两种调用的顺序,将这两种顺序的名称定义为事件冒泡,事件捕获
事件冒泡规定: 从son => father => grandpa 依次触发事件 从图片解释如下图
图中简单的画出了冒泡的顺序
事件捕获规定: 从grandpa => father => son 依次出发 从图片解释如下图
图中简单的画出了捕获的顺序
我们的代码是先遵循冒泡的顺序,还是捕获的顺序可以通过我们自己定义来决定,我们通过常用的增加监听事件的方式来举例
事件绑定api
son.attachEvent('onclick',fn) //IE5冒泡
on.addEventListener('click',fn) //网景捕获
son.addEventListener('click',fn,boolean) //W3C:通过boolean来判断是先捕获还是先冒泡
在W3C规定中添加监听事件的方式,若boolean不传任何值,或者值为false,则让fn走冒泡的形式,如果值为true则让fn走捕获的形式
通过下图大家可以看一下捕获和冒泡的具体运行步骤
同时还有一个特例,若只有一个div被监听,fn在捕获和冒泡阶段监听click事件,用户点击后谁先监听谁先实行,
既然知道了冒泡,那么如果取消冒泡事件呢,
关于如果取消滚动事件冒泡
在探讨取消滚动事件前,先告诉大家如何取消冒泡,同时需要注意的是冒泡可以取消,但是捕获不可取消,
function fn(e) {
e.stopPropagation()} //取消冒泡事件
通过stopPropagation即可取消冒泡事件,但是一般不单独取消冒泡事件,一般用于封装独立组件. 但是stopPropagation却不支持取消滚动事件,那么该如何取消呢? 既然不可以取消滚动事件,但是可以取消滚动
box.addEventListener('wheel', e => {
e.preventDefault() // 即可取消滚动
})
// 同时若想兼容移动端也不许滚动,需要监听另一个事件
box.addEventListener('touchstart', e => {
e.preventDefault() // 取消移动端滚动
})
// 在webkit内核中的css加上这句话,即可将滚动条消失不见,从而彻底取消滚动事件
::-webkit-scrollbar {
display: none; /* Chrome Safari */
}
首先监听内容区的wheel,然后取消默认事件,但是通过滚动条依旧可以滚动,但是我们通过css设定滚动条不显示,即可事件取消滚动事件
关于事件委托
委托: 举个例子,我们平时找房子,但是自己找房子特别的费劲,但是我找中介帮我们找房子,就是一个委托关系,我委托了中介帮我做本该我做的事情.
事件委托:给大家两个场景,如果有100个button需要我们去监听怎么办?
解决方法: 给父元素添加监听事件,然后进行判断,是不是这100个button按钮中的一个,如果是则触发监听事件.
div1.addEventListener('click', (e) => {
const t = e.target;
if(t.tagName.toLowerCase() === 'button') {
console.log('button被点击了')}
}
)
以上代码就是一个事件委托.通过判断元素的类型,然后触发事件
场景二:监听不存在的元素
通过动态生成的元素
setTimeout(() =>{
const button = document.createElement('button')
button.textContent = 'click'
div1.appendChild(button)
})
div1.addEventListener('click', (e) => {
const t = e.target;
if(t.tagName.toLowerCase() === 'button') {
console.log('button被点击了')
}
}
)
监听祖先,等点击时看一下是不是我想要监听的元素即可
封装事件委托
on('click','#div1', 'button', () => {
console.log('button被点击了')
})
function on (eventType, element, selector, fn) {
if(!(element instanceof Element)) {
element = document.querySelector(element)
}
element.addEventListener(eventType, e => {
const t = e.target;
if(t.matches(selector)) {
fn()
}
})
}
此代码封装了一个点击事件.
事件委托优点: 省内存,可以监听动态该元素
关于自定义事件
在这里博主仅直接写出如何实现自定义事件,感兴趣的同学可以看一下.
button.addEventListener('click', () => {
// 创建一个自定义事件
const event = new CustomEvent('su', {
detail: {name: 'su', age: 18},
bubble: true, // 允许冒泡
cancelable: false // 不可取消
})
button.dispatchEvent(event)
})
总结
在DOM的学习中会发现很多有趣的事情,同时在实际运用中也是有必要的,因为jQuery等工具都是依赖于DOM的一些api来完成的,同时冒泡事件有时会对我们的项目起到好处,但有时也会有不好的影响,同时该篇文章还提到了取消默认事件,希望大家可以多去学习原生的内容,而不是仅仅依赖于库工具.
记得持续学习,不断跟进!加油!
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!