vue源码解析:vue事件方法之$off方法的实现原理
vue中事件方法一共就四个,挂载在vue实例上的$off移除事件中心里面某个事件的回调函数,通常会用到,那么$off的内部实现原理是什么呢?下面我们来详细说下$off:vm.$off( [event, callback] )参数:{string | Array<string>} event(只在 2.2.2+ 支持数组){Function} [callback]作用:移除自定义事件监听
vue中事件方法一共就四个,挂载在vue实例上的$off移除事件中心里面某个事件的回调函数,通常会用到,那么$off的内部实现原理是什么呢?下面我们来详细说下$off:
vm.$off( [event, callback] )
参数:
{string | Array<string>} event
(只在 2.2.2+ 支持数组){Function} [callback]
作用:
移除自定义事件监听器。
- 如果没有提供参数,则移除所有的事件监听器;
- 如果只提供了事件,则移除该事件所有的监听器;
- 如果同时提供了事件与回调,则只移除这个回调的监听器。
原理:
该方法用来移除事件中心里面某个事件的回调函数,根据所传入参数的不同,作出不同的处理。
Vue.prototype.$off = function (event, fn) {
const vm: Component = this
// all
if (!arguments.length) {
vm._events = Object.create(null)
return vm
}
// array of events
if (Array.isArray(event)) {
for (let i = 0, l = event.length; i < l; i++) {
this.$off(event[i], fn)
}
return vm
}
// specific event
const cbs = vm._events[event]
if (!cbs) {
return vm
}
if (!fn) {
vm._events[event] = null
return vm
}
if (fn) {
// specific handler
let cb
let i = cbs.length
while (i--) {
cb = cbs[i]
if (cb === fn || cb.fn === fn) {
cbs.splice(i, 1)
break
}
}
}
return vm
}
该方法内部就是通过不断判断所传参数的情况进而进行不同的逻辑处理。
首先,判断如果没有传入任何参数(即arguments.length
为0),这就是第一种情况:如果没有提供参数,则移除所有的事件监听器。我们知道,当前实例上的所有事件都存储在事件中心_events
属性中,要想移除所有的事件,那么只需把_events
属性重新置为空对象即可。
接着,判断如果传入的需要移除的事件名是一个数组,就表示需要一次性移除多个事件,那么我们只需同订阅多个事件一样,遍历该数组,然后将数组中的每一个事件都递归调用$off
方法进行移除即可。
接着,获取到需要移除的事件名在事件中心中对应的回调函数cbs
。
接着,判断如果cbs
不存在,那表明在事件中心从来没有订阅过该事件,那就谈不上移除该事件,直接返回,退出程序即可。
接着,如果cbs
存在,但是没有传入回调函数fn
,这就是第二种情况:如果只提供了事件,则移除该事件所有的监听器。这个也不难,我们知道,在事件中心里面,一个事件名对应的回调函数是一个数组,要想移除所有的回调函数我们只需把它对应的数组设置为null
即可。
接着,如果既传入了事件名,又传入了回调函数,cbs
也存在,那这就是第三种情况:如果同时提供了事件与回调,则只移除这个回调的监听器。那么我们只需遍历所有回调函数数组cbs
,如果cbs
中某一项与fn
相同,或者某一项的fn
属性与fn
相同,那么就将其从数组中删除即可。
就这么简单。
更多推荐
所有评论(0)