Vue原始碼解析(三)
阿新 • • 發佈:2019-01-30
接下來呼叫eventsMixin方法,看名稱就知道是關於事件相關的,主要是在Vue的原型上加入$on,$once,$off,$emit
方法。
Vue.prototype.$on = function (event, fn) {
var this$1 = this;
var vm = this;
if (Array.isArray(event)) {
for (var i = 0, l = event.length; i < l; i++) {
this$1.$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
方法為監聽自定義事件,如果event為陣列,則遍歷event陣列進行監聽。如果為字串則放入vm._events陣列中。這塊還進行了一個事件是否為Hook的正則判斷,暫未搞清楚具體作用。
Vue.prototype.$off = function (event, fn) {
var this$1 = this;
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++) {
this $1.$off(event[i$1], fn);
}
return vm
}
// specific event
var cbs = vm._events[event];
if (!cbs) {
return vm
}
if (arguments.length === 1) {
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
};
$off
方法為解除已繫結的事件,如果off方法不傳任何引數,刪除所有繫結事件。如果event為陣列,則迴圈解除陣列內的事件。如果為字串,事件陣列不存在則直接返回;如果不需要回調,則將相關事件陣列設為null。如果該事件陣列有存在,則遍歷事件陣列,並從陣列中刪除符合條件的事件。
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
方法為繫結僅響應一次事件,響應結束後立即解除繫結。主要是呼叫了$on
方法,同時回撥時呼叫$off方法
解除該事件,並再解除事件後進行回撥。
Vue.prototype.$emit = function (event) {
var vm = this;
{
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);
for (var i = 0, l = cbs.length; i < l; i++) {
cbs[i].apply(vm, args);
}
}
return vm
};
$emit
方法為事件下發的方法,首先進行了一個大小寫的判斷,如果註冊事件和下發事件的大小寫不一致,則發出警告。如果該事件陣列存在,則遍歷事件陣列進行註冊回撥,同時使用apply方法傳遞呼叫時引數。