# 事件流
# 事件产生
事件是用户或浏览器自身执行的某种动作,如click,load和mouseover都是事件的名字。
stopPropagation() 阻止事件传播
preventDefault() 阻止事件的默认行为
# 事件流
冒泡型事件流:从DOM树的叶子到根。【推荐】
addEventListener('type',fn,false) //默认为false冒泡阶段。
捕获型事件流:从DOM树的根到叶子。
addEventListener('type',fn,true)
# passive event listener
addEventListener第三个参数常规情况下true事件捕获()/false(默认事件冒泡)其实并不一定是一个布尔值。他也可以是一个对象,一组配置。
{
// 表示`listener`会在该类型的事件捕获阶段传播到该`EventTarget`时触发
capture: Boolean,
// 表示`listener`在添加之后最多只调用一次。如果是`true`,`listener`会在其被调用之后自动移除
once: Boolean,
// 表示`listener`永远不会调用`preventDefault()`。如果`listener`仍然调用了这个函数,客户端将会忽略它并抛出一个控制台警告
passive: Boolean,
}
因为浏览器无法预先知道一个监听器会不会调用 preventDefault(),它需要等监听器执行完后,再去执行默认行为,而监听器执行是要耗时的,这样就会导致页面卡顿。
假设:当你触摸滑动页面时,页面应该跟随手指一起滚动。而此时你绑定了一个 touchstart 事件,你的事件大概执行 200 毫秒。这时浏览器就犯迷糊了:如果你在事件绑定函数中调用了 preventDefault,那么页面就不应该滚动,如果你没有调用 preventDefault,页面就需要滚动。但是你到底调用了还是没有调用,浏览器不知道。只能先执行你的函数,等 200 毫秒后,绑定事件执行完了,浏览器才知道,“哦,原来你没有阻止默认行为,好的,我马上滚”。此时,页面开始滚。
提前给不需要preventDefault的事件预设 { passive: true },可以避免性能浪费。 { passive: true }来避免浏览器检测这个我们是否有在touch事件的handler里调用preventDefault。在这个时候,如果我们依然调用了preventDefault,就会在控制台打印一个警告。告诉我们这个preventDefault会被忽略。
从Chrome 56开始,如果我们给document绑定touchmove或者touchstart事件的监听器,这个passive是会被默认设置为true以提高性能,具体chromestatue 文档。但是我们大多数人并不知道这点,并且依旧调用了preventDefault。这并不会导致什么页面崩溃级的错误,但是这可能导致我们忽略了一个页面性能优化的点,特别是在移动端这种更加重视性能优化的场景下。
passive部分浏览器支持兼容写法如下
var supportsPassive = false;
try {
var opts = Object.defineProperty({}, 'passive', {
get: function() {
supportsPassive = true;
}
});
window.addEventListener("test", null, opts);
} catch (e) {}
// Use our detect's results.
// passive applied if supported, capture will be false either way.
elem.addEventListener(
'touchstart',
fn,
supportsPassive ? { passive: true } : false
);
# 通用的事件绑定函数
function bindEvent(elm,type,selector,fn){
if(fn === null){
fn = selector
selector = null
}
elem.addEventListener(type,e=>{
let target
//需要代理
if(selector){
//获取触发元素
target = e.target
//matches 判断是否触发元素
if(target.matches(selector)){
fn.call(target,e)
}
}else{
//不需要代理
fn)(e)
}
})
}
# target VS currentTarget
target为目标点
currentTarget不固定会随着事件冒泡和捕获阶段变化。
← JSBridge通信过程 跨域 →