vue2.x源码解析 — resolveConstructorOptions函数

680 阅读1分钟

第一节 入口文件解析中,调用this._init函数时,第一步就是对options进行处理,当我们new Vue时,对options参数对处理会走const ctorOption = resolveConstructorOptions(vm.constructor),我们看一下resolveConstructorOptions具体对实现,可以看到,这个函数主要的作用是返回Vue构造函数上的options,可以通过调用Vue.extend的可以查看该函数的具体执行

export function resolveConstructorOptions (Ctor: Class<Component>) {
    let options = Ctor.options  // Ctor即Vue$3,
    // Ctor.super 来判断该类是否是Vue的子类
    // 有super属性,说明Ctor是Vue.extend构建的子类
    if (Ctor.super) {
        const superOptions = resolveConstructorOptions(Ctor.super)
        const cachedSuperOptions = Ctor.superOptions    // Vue构造函数上的options,如directives, filters, components ...

        /**
         * 父类中的options 有没有发生变化
         *
         * 当为Vue混入一些options时,superOptions会发生变化,
         * 此时于之前子类中存储的cachedSuperOptions已经不等,
         * 所以下面的操作主要就是更新sub.superOptions
         */
        if (superOptions !== cachedSuperOptions) {
            // super option changed,
            // need to resolve new options.
            Ctor.superOptions = superOptions
            // check if there are any late-modified/attached options (#4976)
            const modifiedOptions = resolveModifiedOptions(Ctor)
            // update base extend options
            if (modifiedOptions) {
                extend(Ctor.extendOptions, modifiedOptions)
            }

            // 调用mergeOptions合并父类的options(superOptions)和Ctor的extendOptions
            options = Ctor.options = mergeOptions(superOptions, Ctor.extendOptions)

            if (options.name) {
                options.components[options.name] = Ctor
            }
        }
    }

    return options
}

可以看到,如果Ctor上有super属性,就会执行if代码块里的内容,super属性可参阅Vue.extend里的内容

 Vue.extend = function (extendOptions: Object): Function {
    ...
    Sub['super'] = Super
    ...
}

if代码块中,首先会递归调用resolveConstructorOptions方法,返回"父类"上的options并赋值给superOptions变量。然后把"自身"的options赋值给cachedSuperOptions变量。
然后比较这两个变量的值,当这两个变量值不等时,说明"父类"的options改变过了。例如执行了Vue.mixin方法,这时候就需要把"自身"的superOptions属性替换成最新的。然后通过resolveModifiedOptions检查"自身"的options是否发生变化
举例说明:

var Profile = Vue.extend({
    template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>'
})

Vue.mixin({
    data: function () {
        return {
            firstName: 'Walter',
            lastName: 'White',
            alias: 'Heisenberg'
        }
    }
})
new Profile().$mount('#example')

由于Vue.mixin改变了"父类"options,此时superOptions和cachedSuperOptions就不相等了

function resolveModifiedOptions (Ctor: Class<Component>): ?Object {
    let modified
    const latest = Ctor.options         // 自身的options
    const extended = Ctor.extendOptions // Vue.extend传入的options,详见Vue.extend
    const sealed = Ctor.sealedOptions   // 执行Vue.extend时封装的"自身"options,这个属性就是方便检查"自身"的options有没有变化,详见Vue.extend

    // 遍历当前构造器上的options属性,如果在"自身"封装的options里没有,则证明是新添加的。执行if内的语句。调用dedupe方法,最终返回modified变量(即”自身新添加的options“)
    for (const key in latest) {
        if (latest[key] !== sealed[key]) {
            if (!modified) modified = {}
            modified[key] = dedupe(latest[key], extended[key], sealed[key])
        }
    }
    return modified
}

最后,调用mergeOptions合并父类的options(superOptions)和Ctor的extendOptions,同时,执行完resolveConstructorOptions后,_init函数会调用mergeOptions函数对options进行合并,后续将对mergeOptions进行分析