| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139 |
- /* @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) {
- /* istanbul ignore if */
- if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
- mark('init')
- }
- const vm: Component = this
- // a uid
- vm._uid = uid++
- // 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('init end')
- measure(`${vm._name} init`, 'init', 'init end')
- }
- 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
- }
- }
|