vue 源码 event
2021-01-11 本文已影响0人
Wendy81
在moduel包中 vue/dist/vue.runtime.esm.js
了解vue上的
$on, $emit, $once, $off
//刚开始初执行
eventsMixin(Vue);
......
//这里我们查看对应的函数部分
function eventsMixin (Vue) {
var hookRE = /^hook:/;
Vue.prototype.$on = function (event, fn) {
var vm = this;
if (Array.isArray(event)) {
for (var 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
};
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
};
Vue.prototype.$off = function (event, fn) {
var vm = this;
// all
if (!arguments.length) {
vm._events = Object.create(null);
return vm
}
// array of events
if (Array.isArray(event)) {
for (var i$1 = 0, l = event.length; i$1 < l; i$1++) {
vm.$off(event[i$1], fn);
}
return vm
}
// specific event
var cbs = vm._events[event];
if (!cbs) {
return vm
}
if (!fn) {
vm._events[event] = null;
return vm
}
// specific handler
var cb;
var i = cbs.length;
while (i--) {
cb = cbs[i];
if (cb === fn || cb.fn === fn) {
cbs.splice(i, 1);
break
}
}
return vm
};
Vue.prototype.$emit = function (event) {
var vm = this;
if (process.env.NODE_ENV !== 'production') {
var lowerCaseEvent = event.toLowerCase();
if (lowerCaseEvent !== event && vm._events[lowerCaseEvent]) {
tip(
"Event \"" + lowerCaseEvent + "\" is emitted in component " +
(formatComponentName(vm)) + " but the handler is registered for \"" + event + "\". " +
"Note that HTML attributes are case-insensitive and you cannot use " +
"v-on to listen to camelCase events when using in-DOM templates. " +
"You should probably use \"" + (hyphenate(event)) + "\" instead of \"" + event + "\"."
);
}
}
var cbs = vm._events[event];
if (cbs) {
cbs = cbs.length > 1 ? toArray(cbs) : cbs;
var args = toArray(arguments, 1);
var info = "event handler for \"" + event + "\"";
for (var i = 0, l = cbs.length; i < l; i++) {
invokeWithErrorHandling(cbs[i], vm, args, vm, info);
}
}
return vm
};
}
下面面这样写实际上已经执行了Vue.prototype.$on
<div id ="app">
<HelloWorld @showCityName="clickHanlder" msg="Welcome to Your Vue.js App"/>
</div>
export default {
.....
methods: {
clickHanlder(data){
//这里的data就是下面子组件用$emit调用这个event时传过的参数 {a:10}
alert(data.a)
}
}
}
Vue.prototype.$on = function (event, fn) {
......
console.log(event)
// 这里的event 就是showCityName
.....
}
然后在子组件即HelloWorld中我们可以用Vue.prototype.on定义的事件showCityName
<template>
<div id="hello" class="hello">
<button @click="clickHanlder">click</button>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
methods: {
clickHanlder(){
//这里我们可以用$emit调用父组件的 showCityName事件,并传参过去
this.$emit('showCityName',{a:10})
}
}
}
</script>
从上面的事件中我们可以了解以: