UNPKG

3.97 kBJavaScriptView Raw
1/* @flow */
2
3import config from '../config'
4import { initProxy } from './proxy'
5import { initState } from './state'
6import { initRender } from './render'
7import { initEvents } from './events'
8import { mark, measure } from '../util/perf'
9import { initLifecycle, callHook } from './lifecycle'
10import { initProvide, initInjections } from './inject'
11import { extend, mergeOptions, formatComponentName } from '../util/index'
12
13let uid = 0
14
15export function initMixin (Vue: Class<Component>) {
16 Vue.prototype._init = function (options?: Object) {
17 const vm: Component = this
18 // a uid
19 vm._uid = uid++
20
21 let startTag, endTag
22 /* istanbul ignore if */
23 if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
24 startTag = `vue-perf-start:${vm._uid}`
25 endTag = `vue-perf-end:${vm._uid}`
26 mark(startTag)
27 }
28
29 // a flag to avoid this being observed
30 vm._isVue = true
31 // merge options
32 if (options && options._isComponent) {
33 // optimize internal component instantiation
34 // since dynamic options merging is pretty slow, and none of the
35 // internal component options needs special treatment.
36 initInternalComponent(vm, options)
37 } else {
38 vm.$options = mergeOptions(
39 resolveConstructorOptions(vm.constructor),
40 options || {},
41 vm
42 )
43 }
44 /* istanbul ignore else */
45 if (process.env.NODE_ENV !== 'production') {
46 initProxy(vm)
47 } else {
48 vm._renderProxy = vm
49 }
50 // expose real self
51 vm._self = vm
52 initLifecycle(vm)
53 initEvents(vm)
54 initRender(vm)
55 callHook(vm, 'beforeCreate')
56 initInjections(vm) // resolve injections before data/props
57 initState(vm)
58 initProvide(vm) // resolve provide after data/props
59 callHook(vm, 'created')
60
61 /* istanbul ignore if */
62 if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
63 vm._name = formatComponentName(vm, false)
64 mark(endTag)
65 measure(`vue ${vm._name} init`, startTag, endTag)
66 }
67
68 if (vm.$options.el) {
69 vm.$mount(vm.$options.el)
70 }
71 }
72}
73
74export function initInternalComponent (vm: Component, options: InternalComponentOptions) {
75 const opts = vm.$options = Object.create(vm.constructor.options)
76 // doing this because it's faster than dynamic enumeration.
77 const parentVnode = options._parentVnode
78 opts.parent = options.parent
79 opts._parentVnode = parentVnode
80
81 const vnodeComponentOptions = parentVnode.componentOptions
82 opts.propsData = vnodeComponentOptions.propsData
83 opts._parentListeners = vnodeComponentOptions.listeners
84 opts._renderChildren = vnodeComponentOptions.children
85 opts._componentTag = vnodeComponentOptions.tag
86
87 if (options.render) {
88 opts.render = options.render
89 opts.staticRenderFns = options.staticRenderFns
90 }
91}
92
93export function resolveConstructorOptions (Ctor: Class<Component>) {
94 let options = Ctor.options
95 if (Ctor.super) {
96 const superOptions = resolveConstructorOptions(Ctor.super)
97 const cachedSuperOptions = Ctor.superOptions
98 if (superOptions !== cachedSuperOptions) {
99 // super option changed,
100 // need to resolve new options.
101 Ctor.superOptions = superOptions
102 // check if there are any late-modified/attached options (#4976)
103 const modifiedOptions = resolveModifiedOptions(Ctor)
104 // update base extend options
105 if (modifiedOptions) {
106 extend(Ctor.extendOptions, modifiedOptions)
107 }
108 options = Ctor.options = mergeOptions(superOptions, Ctor.extendOptions)
109 if (options.name) {
110 options.components[options.name] = Ctor
111 }
112 }
113 }
114 return options
115}
116
117function resolveModifiedOptions (Ctor: Class<Component>): ?Object {
118 let modified
119 const latest = Ctor.options
120 const sealed = Ctor.sealedOptions
121 for (const key in latest) {
122 if (latest[key] !== sealed[key]) {
123 if (!modified) modified = {}
124 modified[key] = latest[key]
125 }
126 }
127 return modified
128}