forked from vuejs/vue
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathvirtual-component.js
90 lines (76 loc) · 2.68 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
/* @flow */
// https://github.com/Hanks10100/weex-native-directive/tree/master/component
import { mergeOptions } from 'core/util/index'
import { initProxy } from 'core/instance/proxy'
import { initState } 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, mountComponent, 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')
registerComponentHook(componentId, 'lifecycle', 'attach', () => {
mountComponent(vm)
})
registerComponentHook(componentId, 'lifecycle', 'detach', () => {
vm.$destroy()
})
}
// override Vue.prototype._update
function updateVirtualComponent (vnode: VNode, hydrating?: boolean) {
// TODO
updateComponentData(this.$options.componentId, {})
}
// listening on native callback
export function resolveVirtualComponent (vnode: MountedComponentVNode): VNode {
const BaseCtor = vnode.componentOptions.Ctor
const VirtualComponent = BaseCtor.extend({})
VirtualComponent.prototype._init = initVirtualComponent
VirtualComponent.prototype._update = updateVirtualComponent
vnode.componentOptions.Ctor = BaseCtor.extend({
beforeCreate () {
registerComponentHook(VirtualComponent.cid, 'lifecycle', 'create', componentId => {
// create virtual component
const options = { componentId }
return new VirtualComponent(options)
})
}
})
}