forked from vuejs/vue
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathvirtual-component.js
136 lines (117 loc) · 3.94 KB
/
virtual-component.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/* @flow */
// https://github.com/Hanks10100/weex-native-directive/tree/master/component
import { mergeOptions, isPlainObject, noop } from 'core/util/index'
import Watcher from 'core/observer/watcher'
import { initProxy } from 'core/instance/proxy'
import { initState, getData } from 'core/instance/state'
import { initRender } from 'core/instance/render'
import { initEvents } from 'core/instance/events'
import { initProvide, initInjections } from 'core/instance/inject'
import { initLifecycle, callHook } from 'core/instance/lifecycle'
import { initInternalComponent, resolveConstructorOptions } from 'core/instance/init'
import { registerComponentHook, updateComponentData } from '../../util/index'
let uid = 0
// override Vue.prototype._init
function initVirtualComponent (options: Object = {}) {
const vm: Component = this
const componentId = options.componentId
// virtual component uid
vm._uid = `virtual-component-${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
}
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')
// send initial data to native
const data = vm.$options.data
const params = typeof data === 'function'
? getData(data, vm)
: data || {}
if (isPlainObject(params)) {
updateComponentData(componentId, params)
}
registerComponentHook(componentId, 'lifecycle', 'attach', () => {
callHook(vm, 'beforeMount')
const updateComponent = () => {
vm._update(vm._vnode, false)
}
new Watcher(vm, updateComponent, noop, null, true)
vm._isMounted = true
callHook(vm, 'mounted')
})
registerComponentHook(componentId, 'lifecycle', 'detach', () => {
vm.$destroy()
})
}
// override Vue.prototype._update
function updateVirtualComponent (vnode?: VNode) {
const vm: Component = this
const componentId = vm.$options.componentId
if (vm._isMounted) {
callHook(vm, 'beforeUpdate')
}
vm._vnode = vnode
if (vm._isMounted && componentId) {
// TODO: data should be filtered and without bindings
const data = Object.assign({}, vm._data)
updateComponentData(componentId, data, () => {
callHook(vm, 'updated')
})
}
}
// listening on native callback
export function resolveVirtualComponent (vnode: MountedComponentVNode): VNode {
const BaseCtor = vnode.componentOptions.Ctor
const VirtualComponent = BaseCtor.extend({})
const cid = VirtualComponent.cid
VirtualComponent.prototype._init = initVirtualComponent
VirtualComponent.prototype._update = updateVirtualComponent
vnode.componentOptions.Ctor = BaseCtor.extend({
beforeCreate () {
// const vm: Component = this
// TODO: listen on all events and dispatch them to the
// corresponding virtual components according to the componentId.
// vm._virtualComponents = {}
const createVirtualComponent = (componentId, propsData) => {
// create virtual component
// const subVm =
new VirtualComponent({
componentId,
propsData
})
// if (vm._virtualComponents) {
// vm._virtualComponents[componentId] = subVm
// }
}
registerComponentHook(cid, 'lifecycle', 'create', createVirtualComponent)
},
beforeDestroy () {
delete this._virtualComponents
}
})
}