1
1
import Watcher from '../observer/watcher'
2
- import { extend , query , resolveAsset , hasOwn } from '../util/index'
2
+ import { extend , query , resolveAsset , hasOwn , isArray , isObject } from '../util/index'
3
3
import { createElement , patch , updateListeners } from '../vdom/index'
4
4
import { callHook } from './lifecycle'
5
5
import { getPropValue } from './state'
@@ -18,78 +18,6 @@ export function initRender (vm) {
18
18
}
19
19
}
20
20
21
- function resolveSlots ( vm , children ) {
22
- if ( children ) {
23
- children = children . slice ( )
24
- const slots = { default : children }
25
- let i = children . length
26
- let name , child
27
- while ( i -- ) {
28
- child = children [ i ]
29
- if ( ( name = child . data && child . data . slot ) ) {
30
- let slot = ( slots [ name ] || ( slots [ name ] = [ ] ) )
31
- if ( child . tag === 'template' ) {
32
- slot . push . apply ( slot , child . children )
33
- } else {
34
- slot . push ( child )
35
- }
36
- children . splice ( i , 1 )
37
- }
38
- }
39
- vm . $slots = slots
40
- }
41
- }
42
-
43
- function mergeParentData ( vm , data , parentData ) {
44
- const props = vm . $options . props
45
- if ( parentData . attrs ) {
46
- const attrs = data . attrs || ( data . attrs = { } )
47
- for ( let key in parentData . attrs ) {
48
- if ( ! hasOwn ( props , key ) ) {
49
- attrs [ key ] = parentData . attrs [ key ]
50
- }
51
- }
52
- }
53
- if ( parentData . props ) {
54
- const props = data . props || ( data . props = { } )
55
- for ( let key in parentData . props ) {
56
- if ( ! hasOwn ( props , key ) ) {
57
- props [ key ] = parentData . props [ key ]
58
- }
59
- }
60
- }
61
- if ( parentData . staticClass ) {
62
- data . staticClass = data . staticClass
63
- ? data . staticClass + ' ' + parentData . staticClass
64
- : parentData . staticClass
65
- }
66
- if ( parentData . class ) {
67
- extend ( ( data . class || ( data . class = { } ) ) , parentData . class )
68
- }
69
- if ( parentData . style ) {
70
- extend ( ( data . style || ( data . style = { } ) ) , parentData . style )
71
- }
72
- if ( parentData . directives ) {
73
- data . directives = parentData . directives . conact ( data . directives || [ ] )
74
- }
75
- if ( parentData . on ) {
76
- updateListeners ( parentData . on , data . on || { } , ( event , handler ) => {
77
- vm . $on ( event , handler )
78
- } )
79
- }
80
- }
81
-
82
- function updateProps ( vm , data ) {
83
- if ( data . attrs || data . props ) {
84
- for ( let key in vm . $options . props ) {
85
- let newVal = getPropValue ( data , key )
86
- if ( vm [ key ] !== newVal ) {
87
- vm [ key ] = newVal
88
- }
89
- }
90
- }
91
- }
92
-
93
21
export function renderMixin ( Vue ) {
94
22
// shorthands used in render functions
95
23
Vue . prototype . __h__ = createElement
@@ -112,21 +40,21 @@ export function renderMixin (Vue) {
112
40
}
113
41
}
114
42
115
- Vue . prototype . _tryUpdate = function ( data , children , key ) {
43
+ Vue . prototype . _tryUpdate = function ( parentData , children , key ) {
44
+ const oldParentData = this . $options . _renderData
116
45
this . $options . _renderKey = key
117
- this . $options . _renderData = data
46
+ this . $options . _renderData = parentData
118
47
this . $options . _renderChildren = children
119
- // set props - this will trigger update if any of them changed
120
- // but not guaranteed
121
- if ( data ) {
122
- updateProps ( this , data )
48
+ // update props and listeners
49
+ if ( parentData ) {
50
+ updateProps ( this , parentData )
51
+ updateEvents ( this , parentData )
123
52
}
124
53
// for now, if the component has content it always updates
125
54
// because we don't know whether the children have changed.
126
55
// need to optimize in the future.
127
- if ( children ) {
56
+ if ( children || diffParentData ( parentData , oldParentData ) ) {
128
57
this . $forceUpdate ( )
129
- return
130
58
}
131
59
}
132
60
@@ -172,3 +100,113 @@ export function renderMixin (Vue) {
172
100
this . _watcher . update ( )
173
101
}
174
102
}
103
+
104
+ function resolveSlots ( vm , children ) {
105
+ if ( children ) {
106
+ children = children . slice ( )
107
+ const slots = { default : children }
108
+ let i = children . length
109
+ let name , child
110
+ while ( i -- ) {
111
+ child = children [ i ]
112
+ if ( ( name = child . data && child . data . slot ) ) {
113
+ let slot = ( slots [ name ] || ( slots [ name ] = [ ] ) )
114
+ if ( child . tag === 'template' ) {
115
+ slot . push . apply ( slot , child . children )
116
+ } else {
117
+ slot . push ( child )
118
+ }
119
+ children . splice ( i , 1 )
120
+ }
121
+ }
122
+ vm . $slots = slots
123
+ }
124
+ }
125
+
126
+ function diffParentData ( data , oldData ) {
127
+ let key , old , cur
128
+ for ( key in oldData ) {
129
+ cur = data [ key ]
130
+ old = oldData [ key ]
131
+ if ( key === 'on' ) continue
132
+ if ( ! cur ) return true
133
+ if ( isArray ( old ) ) {
134
+ if ( ! isArray ( cur ) ) return true
135
+ if ( cur . length !== old . length ) return true
136
+ for ( let i = 0 ; i < old . length ; i ++ ) {
137
+ if ( isObject ( old [ i ] ) ) {
138
+ if ( ! isObject ( cur [ i ] ) ) return true
139
+ if ( diffObject ( cur , old ) ) return true
140
+ } else if ( old [ i ] !== cur [ i ] ) {
141
+ return true
142
+ }
143
+ }
144
+ } else if ( diffObject ( cur , old ) ) {
145
+ return true
146
+ }
147
+ }
148
+ }
149
+
150
+ function diffObject ( cur , old ) {
151
+ for ( var key in old ) {
152
+ if ( cur [ key ] !== old [ key ] ) return true
153
+ }
154
+ }
155
+
156
+ function mergeParentData ( vm , data , parentData ) {
157
+ const props = vm . $options . props
158
+ if ( parentData . attrs ) {
159
+ const attrs = data . attrs || ( data . attrs = { } )
160
+ for ( let key in parentData . attrs ) {
161
+ if ( ! hasOwn ( props , key ) ) {
162
+ attrs [ key ] = parentData . attrs [ key ]
163
+ }
164
+ }
165
+ }
166
+ if ( parentData . props ) {
167
+ const props = data . props || ( data . props = { } )
168
+ for ( let key in parentData . props ) {
169
+ if ( ! hasOwn ( props , key ) ) {
170
+ props [ key ] = parentData . props [ key ]
171
+ }
172
+ }
173
+ }
174
+ if ( parentData . staticClass ) {
175
+ data . staticClass = data . staticClass
176
+ ? data . staticClass + ' ' + parentData . staticClass
177
+ : parentData . staticClass
178
+ }
179
+ if ( parentData . class ) {
180
+ if ( ! data . class ) {
181
+ data . class = parentData . class
182
+ } else {
183
+ data . class = ( isArray ( data . class ) ? data . class : [ ] ) . concat ( parentData . class )
184
+ }
185
+ }
186
+ if ( parentData . style ) {
187
+ if ( ! data . style ) {
188
+ data . style = parentData . style
189
+ } else {
190
+ extend ( data . style , parentData . style )
191
+ }
192
+ }
193
+ if ( parentData . directives ) {
194
+ data . directives = parentData . directives . conact ( data . directives || [ ] )
195
+ }
196
+ }
197
+
198
+ function updateProps ( vm , data ) {
199
+ if ( data . attrs || data . props ) {
200
+ for ( let key in vm . $options . props ) {
201
+ vm [ key ] = getPropValue ( data , key )
202
+ }
203
+ }
204
+ }
205
+
206
+ function updateEvents ( vm , data ) {
207
+ if ( data . on ) {
208
+ updateListeners ( data . on , vm . _vnode . data . on || { } , ( event , handler ) => {
209
+ vm . $on ( event , handler )
210
+ } )
211
+ }
212
+ }
0 commit comments