/* @flow */ import config from '../config' import { initProxy } from './proxy' import { initState } from './state' import { initRender } from './render' import { initEvents } from './events' import { mark, measure } from '../util/perf' import { initLifecycle, callHook } from './lifecycle' import { initProvide, initInjections } from './inject' import { extend, mergeOptions, formatComponentName } from '../util/index' let uid = 0 export function initMixin (Vue: Class<Component>) { Vue.prototype._init = function (options?: Object) { const vm: Component = this // a uid vm._uid = uid++ let startTag, endTag /* istanbul ignore if */ if (process.env.NODE_ENV !== 'production' && config.performance && mark) { startTag = `vue-perf-init:${vm._uid}` endTag = `vue-perf-end:${vm._uid}` mark(startTag) } // a flag to avoid this being observed vm._isVue = true // merge options if (options && options._isComponent) { // optimize internal component instantiation // since dynamic options merging is pretty slow, and none of the // internal component options needs special treatment. initInternalComponent(vm, options) } else { vm.$options = mergeOptions( resolveConstructorOptions(vm.constructor), options || {}, vm ) } /* istanbul ignore else */ if (process.env.NODE_ENV !== 'production') { initProxy(vm) } else { vm._renderProxy = vm } // expose real self vm._self = vm initLifecycle(vm) initEvents(vm) initRender(vm) callHook(vm, 'beforeCreate') initInjections(vm) // resolve injections before data/props initState(vm) initProvide(vm) // resolve provide after data/props callHook(vm, 'created') /* istanbul ignore if */ if (process.env.NODE_ENV !== 'production' && config.performance && mark) { vm._name = formatComponentName(vm, false) mark(endTag) measure(`${vm._name} init`, startTag, endTag) } if (vm.$options.el) { vm.$mount(vm.$options.el) } } } function initInternalComponent (vm: Component, options: InternalComponentOptions) { const opts = vm.$options = Object.create(vm.constructor.options) // doing this because it's faster than dynamic enumeration. opts.parent = options.parent opts.propsData = options.propsData opts._parentVnode = options._parentVnode opts._parentListeners = options._parentListeners opts._renderChildren = options._renderChildren opts._componentTag = options._componentTag opts._parentElm = options._parentElm opts._refElm = options._refElm if (options.render) { opts.render = options.render opts.staticRenderFns = options.staticRenderFns } } export function resolveConstructorOptions (Ctor: Class<Component>) { let options = Ctor.options if (Ctor.super) { const superOptions = resolveConstructorOptions(Ctor.super) const cachedSuperOptions = Ctor.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) } options = Ctor.options = mergeOptions(superOptions, Ctor.extendOptions) if (options.name) { options.components[options.name] = Ctor } } } return options } function resolveModifiedOptions (Ctor: Class<Component>): ?Object { let modified const latest = Ctor.options const sealed = Ctor.sealedOptions for (const key in latest) { if (latest[key] !== sealed[key]) { if (!modified) modified = {} modified[key] = dedupe(latest[key], sealed[key]) } } return modified } function dedupe (latest, sealed) { // compare latest and sealed to ensure lifecycle hooks won't be duplicated // between merges if (Array.isArray(latest)) { const res = [] sealed = Array.isArray(sealed) ? sealed : [sealed] for (let i = 0; i < latest.length; i++) { if (sealed.indexOf(latest[i]) < 0) { res.push(latest[i]) } } return res } else { return latest } }
所有评论(0)