-
Notifications
You must be signed in to change notification settings - Fork 668
/
Copy pathTransitionStub.js
147 lines (128 loc) · 3.65 KB
/
TransitionStub.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
136
137
138
139
140
141
142
143
144
145
146
147
// @flow
import { warn } from 'shared/util'
function getRealChild(vnode: ?VNode): ?VNode {
const compOptions = vnode && vnode.componentOptions
if (compOptions && compOptions.Ctor.options.abstract) {
return getRealChild(getFirstComponentChild(compOptions.children))
} else {
return vnode
}
}
function isSameChild(child: VNode, oldChild: VNode): boolean {
return oldChild.key === child.key && oldChild.tag === child.tag
}
function getFirstComponentChild(children: ?Array<VNode>): ?VNode {
if (Array.isArray(children)) {
for (let i = 0; i < children.length; i++) {
const c = children[i]
if (c && (c.componentOptions || isAsyncPlaceholder(c))) {
return c
}
}
}
}
function isPrimitive(value: any): boolean {
return (
typeof value === 'string' ||
typeof value === 'number' ||
// $FlowIgnore
typeof value === 'symbol' ||
typeof value === 'boolean'
)
}
function isAsyncPlaceholder(node: VNode): boolean {
return node.isComment && node.asyncFactory
}
const camelizeRE = /-(\w)/g
export const camelize = (str: string): string => {
return str.replace(camelizeRE, (_, c) => (c ? c.toUpperCase() : ''))
}
function hasParentTransition(vnode: VNode): ?boolean {
while ((vnode = vnode.parent)) {
if (vnode.data.transition) {
return true
}
}
}
export default {
render(h: Function) {
let children: ?Array<VNode> = this.$options._renderChildren
if (!children) {
return
}
// filter out text nodes (possible whitespaces)
children = children.filter((c: VNode) => c.tag || isAsyncPlaceholder(c))
/* istanbul ignore if */
if (!children.length) {
return
}
// warn multiple elements
if (children.length > 1) {
warn(
`<transition> can only be used on a single element. ` +
`Use ` +
'<transition-group> for lists.'
)
}
const mode: string = this.mode
// warn invalid mode
if (mode && mode !== 'in-out' && mode !== 'out-in') {
warn('invalid <transition> mode: ' + mode)
}
const rawChild: VNode = children[0]
// if this is a component root node and the component's
// parent container node also has transition, skip.
if (hasParentTransition(this.$vnode)) {
return rawChild
}
// apply transition data to child
// use getRealChild() to ignore abstract components e.g. keep-alive
const child: ?VNode = getRealChild(rawChild)
if (!child) {
return rawChild
}
const id: string = `__transition-${this._uid}-`
child.key =
child.key == null
? child.isComment
? id + 'comment'
: id + child.tag
: isPrimitive(child.key)
? String(child.key).indexOf(id) === 0
? child.key
: id + child.key
: child.key
const data: Object = child.data || (child.data = {})
const oldRawChild: ?VNode = this._vnode
const oldChild: ?VNode = getRealChild(oldRawChild)
if (
child.data.directives &&
child.data.directives.some(d => d.name === 'show')
) {
child.data.show = true
}
// mark v-show
// so that the transition module can hand over the control
// to the directive
if (
child.data.directives &&
child.data.directives.some(d => d.name === 'show')
) {
child.data.show = true
}
if (
oldChild &&
oldChild.data &&
!isSameChild(child, oldChild) &&
!isAsyncPlaceholder(oldChild) &&
// #6687 component root is a comment node
!(
oldChild.componentInstance &&
oldChild.componentInstance._vnode.isComment
)
) {
oldChild.data = { ...data }
}
return rawChild
}
}