acd2a00103e69acbda5db278b704a6c34beadbcccf091bd6cc0778af49c1a510f73bfdceb94aeacdb53f1b0c0cd102fa482881ca18e09e96d3fccf81e0e3fc 3.9 KB

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