6081389867f54ea6bd84c29f9c4b7540f50483f77d815471180b7f6ee64d6927451e7491aca0b8c9c5f123313574de54392c09cfddfc226519c6a023a42faa 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. /* @flow */
  2. // https://github.com/Hanks10100/weex-native-directive/tree/master/component
  3. import { mergeOptions, isPlainObject, noop } from 'core/util/index'
  4. import Watcher from 'core/observer/watcher'
  5. import { initProxy } from 'core/instance/proxy'
  6. import { initState, getData } from 'core/instance/state'
  7. import { initRender } from 'core/instance/render'
  8. import { initEvents } from 'core/instance/events'
  9. import { initProvide, initInjections } from 'core/instance/inject'
  10. import { initLifecycle, callHook } from 'core/instance/lifecycle'
  11. import { initInternalComponent, resolveConstructorOptions } from 'core/instance/init'
  12. import { registerComponentHook, updateComponentData } from '../../util/index'
  13. let uid = 0
  14. // override Vue.prototype._init
  15. function initVirtualComponent (options: Object = {}) {
  16. const vm: Component = this
  17. const componentId = options.componentId
  18. // virtual component uid
  19. vm._uid = `virtual-component-${uid++}`
  20. // a flag to avoid this being observed
  21. vm._isVue = true
  22. // merge options
  23. if (options && options._isComponent) {
  24. // optimize internal component instantiation
  25. // since dynamic options merging is pretty slow, and none of the
  26. // internal component options needs special treatment.
  27. initInternalComponent(vm, options)
  28. } else {
  29. vm.$options = mergeOptions(
  30. resolveConstructorOptions(vm.constructor),
  31. options || {},
  32. vm
  33. )
  34. }
  35. /* istanbul ignore else */
  36. if (process.env.NODE_ENV !== 'production') {
  37. initProxy(vm)
  38. } else {
  39. vm._renderProxy = vm
  40. }
  41. vm._self = vm
  42. initLifecycle(vm)
  43. initEvents(vm)
  44. initRender(vm)
  45. callHook(vm, 'beforeCreate')
  46. initInjections(vm) // resolve injections before data/props
  47. initState(vm)
  48. initProvide(vm) // resolve provide after data/props
  49. callHook(vm, 'created')
  50. // send initial data to native
  51. const data = vm.$options.data
  52. const params = typeof data === 'function'
  53. ? getData(data, vm)
  54. : data || {}
  55. if (isPlainObject(params)) {
  56. updateComponentData(componentId, params)
  57. }
  58. registerComponentHook(componentId, 'lifecycle', 'attach', () => {
  59. callHook(vm, 'beforeMount')
  60. const updateComponent = () => {
  61. vm._update(vm._vnode, false)
  62. }
  63. new Watcher(vm, updateComponent, noop, null, true)
  64. vm._isMounted = true
  65. callHook(vm, 'mounted')
  66. })
  67. registerComponentHook(componentId, 'lifecycle', 'detach', () => {
  68. vm.$destroy()
  69. })
  70. }
  71. // override Vue.prototype._update
  72. function updateVirtualComponent (vnode?: VNode) {
  73. const vm: Component = this
  74. const componentId = vm.$options.componentId
  75. if (vm._isMounted) {
  76. callHook(vm, 'beforeUpdate')
  77. }
  78. vm._vnode = vnode
  79. if (vm._isMounted && componentId) {
  80. // TODO: data should be filtered and without bindings
  81. const data = Object.assign({}, vm._data)
  82. updateComponentData(componentId, data, () => {
  83. callHook(vm, 'updated')
  84. })
  85. }
  86. }
  87. // listening on native callback
  88. export function resolveVirtualComponent (vnode: MountedComponentVNode): VNode {
  89. const BaseCtor = vnode.componentOptions.Ctor
  90. const VirtualComponent = BaseCtor.extend({})
  91. const cid = VirtualComponent.cid
  92. VirtualComponent.prototype._init = initVirtualComponent
  93. VirtualComponent.prototype._update = updateVirtualComponent
  94. vnode.componentOptions.Ctor = BaseCtor.extend({
  95. beforeCreate () {
  96. // const vm: Component = this
  97. // TODO: listen on all events and dispatch them to the
  98. // corresponding virtual components according to the componentId.
  99. // vm._virtualComponents = {}
  100. const createVirtualComponent = (componentId, propsData) => {
  101. // create virtual component
  102. // const subVm =
  103. new VirtualComponent({
  104. componentId,
  105. propsData
  106. })
  107. // if (vm._virtualComponents) {
  108. // vm._virtualComponents[componentId] = subVm
  109. // }
  110. }
  111. registerComponentHook(cid, 'lifecycle', 'create', createVirtualComponent)
  112. },
  113. beforeDestroy () {
  114. delete this._virtualComponents
  115. }
  116. })
  117. }