触发自定义事件事件思路不复杂:根据事件名找到对应的回调数组,然后遍历执行就好了(注意this指向)。

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
};

这里有这么个问题,里面的toArray方法起到什么作用?我先把toArray的实现抄下来:

function toArray (list, start) {
    start = start || 0;
    var i = list.length - start;
    var ret = new Array(i);
    while (i--) {
        ret[i] = list[i + start];
    }
    return ret
}

关于arguments的那个toArray,我想起来了underscore.js中optimizeCb这个函数,其本质上是arguments自身的性能问题。在这里将类数组arguments转换成真数组可以提高性能。

那针对回调数组的toArray起到了什么作用?联想到上一节所说的$once方法,我们可以看出回调在执行的时候可能会改变这个回调数组,如果我们根据原回调数组去遍历可能会出错。所以我们取了一个新回调数组,按照新回调数组去遍历,改变原回调数组并不会影响新回调数组。

results matching ""

    No results matching ""