$emit
与$on
vue 事件相关的函数挂载在vue的原型对象上面。分别为:vue
$on
vm.$on(event, callback)
数组
const hookRE = /^hook:/
Vue.prototype.$on = function (event: string | Array<string>, fn: Function): Component {
const vm: Component = this
if (Array.isArray(event)) {
for (let i = 0, l = event.length; i < l; i++) {
vm.$on(event[i], fn)
}
} else {
(vm._events[event] || (vm._events[event] = [])).push(fn)
// optimize hook:event cost by using a boolean flag marked at registration
// instead of a hash lookup
if (hookRE.test(event)) {
vm._hasHookEvent = true
}
}
return vm
}
复制代码
$on
负责注册函数,事件以数组形式存贮在vm
的_event
属性上。$on第一个参数容许传入字符串数组,数组的每一个成员对应的函数都是fn。 注意第一行定义了hookRE=/^hook:/
这个正则,这样作的目的是:bash
vm.$on('hook:created', fn)
复制代码
当注册了一个hook:+声明周期
的钩子函数以后,vue内部会在调用组件options提供的声明周期函数后还会调用一次用户经过$on注册的钩子函数。app
$off
vm.$off([event, callback])
函数
Vue.prototype.$off = function (event, fn) {
var this$1 = this;
var vm = this;
// 若是未传入任何参数,则删除全部事件
if (!arguments.length) {
vm._events = Object.create(null);
return vm
}
// 数组形式循环删除数组的每一项事件
// 对应$on以数据形式注册函数
if (Array.isArray(event)) {
for (var i = 0, l = event.length; i < l; i++) {
this$1.$off(event[i], fn);
}
return vm
}
// 若是不存在该事件,则返回
var cbs = vm._events[event];
if (!cbs) {
return vm
}
// 若是存在该event,但未传入钩子函数,则将事件置空。
if (!fn) {
vm._events[event] = null;
return vm
}
if (fn) {
// specific handler
var cb;
var i$1 = cbs.length;
// 循环删除事件数组对应的每一项
while (i$1--) {
cb = cbs[i$1];
// 注意这里的fn是引用传递,对应的内存函数是一个
// 不然两个单独内存的函数没法进行比较
if (cb === fn || cb.fn === fn) {
cbs.splice(i$1, 1);
break
}
}
}
return vm
};
复制代码
$once
vm.$once(event, fn)
ui
Vue.prototype.$once = function (event, fn) {
var vm = this;
function on () {
vm.$off(event, on);
fn.apply(vm, arguments);
}
on.fn = fn;
vm.$on(event, on);
return vm
};
复制代码
这里的$once
其实是将传入的event
事件作了一个拦截改写,将fn钩子函数改写成on
函数,on
函数在调用时会先卸载改写的事件,并经过必包调用传入的原始钩子函数fn
,注意这里将fn
挂载在on
删除上,是为了在调用off
卸载事件时进行比较。this
$emit
vm.$emit(event, [...args])
spa
Vue.prototype.$emit = function (event) {
var vm = this;
var cbs = vm._events[event];
if (cbs) {
cbs = cbs.length > 1 ? toArray(cbs) : cbs;
// 获取除event以外的全部参数
var args = toArray(arguments, 1);
// 循环调用事件数组的每一项
for (var i = 0, l = cbs.length; i < l; i++) {
try {
// 给事件this绑定为vm
cbs[i].apply(vm, args);
} catch (e) {
handleError(e, vm, ("event handler for \"" + event + "\""));
}
}
}
return vm
};
}
复制代码
$emit
做用是充当发布者的角色触发事件,而全部的事件会以数组形式存储在vm的_event中。prototype
callhook
callhook
不算是vue event事件相关的成员函数,但vue的声明周期函数都是经过callhook
函数调用,也算是充当发布者的角色。code
function callHook (vm, hook) {
...
var handlers = vm.$options[hook];
var info = hook + " hook";
if (handlers) {
for (var i = 0, j = handlers.length; i < j; i++) {
invokeWithErrorHandling(handlers[i], vm, null, vm, info);
}
}
if (vm._hasHookEvent) {
vm.$emit('hook:' + hook);
}
...
}
复制代码
首先,callHook
会先调用组件options
上挂载的声明周期函数。在介绍$on
方法时,发现只要以hook:
注册的声明周期钩子函数,会将_hasHookEvent
变为true
,这时,再经过callhook
调用options
的声明周期钩子函数时,还会在调用以hook:
事件挂载在vm._event上的钩子函数。
所以,当咱们想监听声明周期函数是否调用时,能够经过vm.$on('hook:created', cb)
来实现。
文章内容若有错误,敬请谅解,但愿能够不吝赐教
转载请注明出处,感谢