事件处理后续
前文谈及了实现on()
函数的实现,对当中的one参数和off()函数填坑
one参数用于区分one()
和on()
,one()
函数只是多一个特点,事件函数只触发一次,触发后便移除
jquery.fn.extend({
on(types, selector, data, fn) {
return on(this, types, selector, data, fn);
},
one(types, selector, data, fn) {
return on(this, types, selector, data, fn, 1);
},
})
而涉及到移除,需要看另一个函数off()
,移除事件函数
off([type[, fn]])
-
概述:移除事件绑定
-
解析:
- 前面已经为事件移除做好了铺垫,只要根据参数做出不同反应就成
- 没有参数时,是移除掉所有事件,不分类型
- 只提供了类型,将此类型所有的事件移除
- 只提供事件不行,并不会去翻找所有事件类型,将此事件删除
- 提供类型和事件,定点清除,绑定了多次的需要全部清除
-
实现:
off(type, fn) { //没有参数时移除全部事件 if (arguments.length === 0) { return this.each(function() { //遍历对象的事件存储属性 $.each(this._eventsCache, (index, value) => { //index === 事件类型 value === 数组 //遍历这个数组 $.each(value, (_i, target) => { //target === 对象 this.removeEventListener(index, target.callback); }); }); this._eventsCache = {}; }); } else if (arguments.length === 1) { //移除指定类型的事件 return this.each(function() { $.each(this._eventsCache[type], (_i, target) => { this.removeEventListener(type, target.callback); }); this._eventsCache[type] = []; }); } else { //根据特定事件,移除 return this.each(function() { //先找到相应的事件 if (this._eventsCache && this._eventsCache[type]) { const arr = this._eventsCache[type]; for (let i = 0; i < arr.length; i++) { const target = arr[i]; if (target.fn === fn) { this.removeEventListener(type, target.callback); arr.splice(i, 1); i--; } } } }); } }
事实上还有一个参数,根据委托选择器删除,这一点并没有在此展开了
对于其他事件,只是on()
函数的简化版
jquery.each(["blur", "change", "click", "dblclick", "error",
"focus", "focusin", "focusout", "keydown", "keypress",
"keyup", "mousedown", "mouseenter", "mouseleave",
"mousemove", "mouseout", "mouseover", "mouseup",
"resize", "scroll", "select", "submit", "unload"], function(_i, type) {
jquery.fn[type] = function(data, fn) {
//没有参数的时候,是触发
if (arguments.length === 0) {
return this.each(function() {
$.each(this._eventsCache[type], (_i, target) => {
target.callback.call(this);
});
});
} else {
if (arguments.length === 1) {
fn = data;
data = null;
}
return this.on(type, null, data, fn);
}
};
文档处理补充
事件移除实现之后,回头将前面遗漏的文档方法做一个补充
empty()
-
概述:移除所有子节点
-
实现:
empty() { return this.each(function() { this.innerHTML = ""; }); }
detach([expr])
-
概述:移除元素本身
-
解析:
- 可以接收一个参数,作为筛选表达式
-
实现:
detach(expr) { //没有参数或不合理参数时触发 if (arguments.length === 0 || !isString(expr)) { return this.each(function() { this.remove(); }); } //先选择到表达式 return this.each((_i, value) => { this.constructor(expr).each(function() { this === value && this.remove(); }); }); }
remvoe([expr])
-
概述:移除元素本身,并移除事件
-
解析:
- 简单看,就是一个组合动作,直接拿来用
-
实现:
remove(expr) { return this.off().detach(expr); }
clone([dataAndEvents[, deepDataAndEvents]])
-
概述:克隆节点
-
解析:
- 两个可选参数,控制克隆表现,皆为布尔类型
- 第一参数决定是否克隆节点事件
- 当第一参数开启时,才关注第二参数
- 第二参数默认为
true
,决定是否克隆子节点的事件 - 返回值是一个克隆的新对象
-
实现:
clone(dataAndEvents = false, deepDataAndEvents = true) { const obj = this.constructor(); this.each(function() { const node = this.cloneNode(true); if (dataAndEvents) { node._eventsCache = this._eventsCache; //遍历事件数据,再加一层 $.each(this._eventsCache, function(key) { $.each(this, function() { node.addEventListener(key, this.callback); }); }); //克隆子元素的事件 if (deepDataAndEvents && node.children.length) { $.each(node.children, (index, value) => { node.insertBefore($(this.children[index]).clone(true, true)[0], value); value.remove(); }); } } obj.push(node); }); return obj; }
unwrap()
-
概述:将自己的父元素移除
-
解析:
- 找到自己的父级元素,调用删除指令,不过不能把子元素移除掉了
- 先将所有子元素移出来当作父级元素的兄弟
-
实现:
unwrap() { return this.each(function() { const target = this.parentNode; $(target).after(target.children).remove(); }); }
wrap(content)
-
概述:在自己外围生成一圈元素包裹
-
解析:
- 与上者表现相反,添加
-
实现:
wrap(content) { const target = this.constructor(content).clone(true); return this.after(target).appendTo(target); }
似乎还接收函数参数,将返回值作为外层包裹元素,此处并没有落实
wrapAll(content)
-
概述:将所有匹配元素使用一个元素包裹起来
-
解析:
- 上者是每个匹配元素都生成一个,而此处是将所有匹配元素集合在一块,并使用一个元素包裹
-
实现:
wrapAll(content) { const target = this.constructor(content).clone(true); //将参数放置于第一个目标的附近 return this.first().after(target).end().appendTo(target); }
wrapInner(content)
-
概述:所有子元素用参数包裹起来
-
解析:
- 便是在自己的下围再圈一层
-
实现:
wrapInner(content) { const target = $(content).first(); return this.each(function() { $(this).append(target.clone(true).append($(this.children))); }); },
replaceWith(content)
-
概述:自己作为地点,被参数替换
-
解析:
- 是一整个全部切换
-
实现:
replaceWith(content) { const target = $(content); const obj = this.before(target); this.remove(); return obj; }
replaceAll(content)
-
概述:将自身放置目标值位置,且将目标值移除
-
解析:
- 与前者不同之处,只是参数和匹配元素交换了一下
-
实现:
replaceAll(content) { const target = $(content); const obj = this.insertAfter(target); target.remove(); return obj; }