vue中事件方法一共就四个,挂载在vue实例上的$once用来监听某个自定义事件,通常会用到,那么$once的内部实现原理是什么呢?下面我们来详细说下$once:
参数:
-
{string} event
-
{Function} callback
作用:
监听一个自定义事件,但是只触发一次。一旦触发之后,监听器就会被移除。
原理:
Vue.prototype.$once = function (event, fn) {
const vm: Component = this
function on () {
vm.$off(event, on)
fn.apply(vm, arguments)
}
on.fn = fn
vm.$on(event, on)
return vm
}
我们可以看到$once函数的逻辑其实很简单,在函数的内部声明了一个on函数,on函数里面第一步移除传入的事件,第二部执行回掉,所以当订阅$on事件的时候,此时执行的就是on方法,这样就实现了事件执行一次后直接将事件删除的功能。但是你会发现有一行代码on.fn = fn,这是什么操作呢?我们用子函数
on
替换了原本的订阅事件所对应的回调
fn
,那么在事件中心
_events
属性中存储的该事件名就会变成如下这个样子:
vm._events = {
'xxx':[on]
}
但是用户自己却不知道传入的
fn
被替换了,当用户在触发该事件之前想调用
$off
方法移除该事件时:
vm.$off('xxx',fn)
此时就会出现问题,因为在
_events
属性中的事件名
xxx
对应的回调函数列表中没有
fn
,那么就会移除失败。这就让用户费解了,用户明明给
xxx
事件传入的回调函数是
fn
,现在反而找不到
fn
导致事件移除不了了。
所以,为了解决这一问题,我们需要给
on
上绑定一个
fn
属性,属性值为用户传入的回调
fn
,这样在使用
$off
移除事件的时候,
$off
内部会判断如果回调函数列表中某一项的
fn
属性与
fn
相同时,就可以成功移除事件了。
这就是vue的$once方法的原理。