1
+ import CodeBuilder from '../../../utils/CodeBuilder.js' ;
1
2
import deindent from '../../../utils/deindent.js' ;
2
3
import getBuilders from '../utils/getBuilders.js' ;
3
4
@@ -22,16 +23,42 @@ export default {
22
23
const anchor = `${ name } _anchor` ;
23
24
generator . createAnchor ( anchor , `#each ${ generator . source . slice ( node . expression . start , node . expression . end ) } ` ) ;
24
25
25
- generator . current . builders . init . addBlock ( deindent `
26
- var ${ name } _value = ${ snippet } ;
27
- var ${ iterations } = [];
28
- ${ node . else ? `var ${ elseName } = null;` : '' }
26
+ generator . current . builders . init . addLine ( `var ${ name } _value = ${ snippet } ;` ) ;
27
+ generator . current . builders . init . addLine ( `var ${ iterations } = [];` ) ;
28
+ if ( node . key ) generator . current . builders . init . addLine ( `var ${ name } _lookup = Object.create( null );` ) ;
29
+ if ( node . else ) generator . current . builders . init . addLine ( `var ${ elseName } = null;` ) ;
30
+
31
+ const initialRender = new CodeBuilder ( ) ;
32
+
33
+ const localVars = { } ;
34
+
35
+ if ( node . key ) {
36
+ localVars . fragment = generator . current . getUniqueName ( 'fragment' ) ;
37
+ localVars . value = generator . current . getUniqueName ( 'value' ) ;
38
+ localVars . key = generator . current . getUniqueName ( 'key' ) ;
39
+
40
+ initialRender . addBlock ( deindent `
41
+ var ${ localVars . key } = ${ name } _value[${ i } ].${ node . key } ;
42
+ ${ name } _iterations[${ i } ] = ${ name } _lookup[ ${ localVars . key } ] = ${ renderer } ( ${ params } , ${ listName } , ${ listName } [${ i } ], ${ i } , component${ node . key ? `, ${ localVars . key } ` : `` } );
43
+ ` ) ;
44
+ } else {
45
+ initialRender . addLine (
46
+ `${ name } _iterations[${ i } ] = ${ renderer } ( ${ params } , ${ listName } , ${ listName } [${ i } ], ${ i } , component );`
47
+ ) ;
48
+ }
29
49
50
+ if ( ! isToplevel ) {
51
+ initialRender . addLine (
52
+ `${ name } _iterations[${ i } ].mount( ${ anchor } .parentNode, ${ anchor } );`
53
+ ) ;
54
+ }
55
+
56
+ generator . current . builders . init . addBlock ( deindent `
30
57
for ( var ${ i } = 0; ${ i } < ${ name } _value.length; ${ i } += 1 ) {
31
- ${ iterations } [${ i } ] = ${ renderer } ( ${ params } , ${ listName } , ${ listName } [${ i } ], ${ i } , component );
32
- ${ ! isToplevel ? `${ iterations } [${ i } ].mount( ${ anchor } .parentNode, ${ anchor } );` : '' }
58
+ ${ initialRender }
33
59
}
34
60
` ) ;
61
+
35
62
if ( node . else ) {
36
63
generator . current . builders . init . addBlock ( deindent `
37
64
if ( !${ name } _value.length ) {
@@ -56,24 +83,62 @@ export default {
56
83
}
57
84
}
58
85
59
- generator . current . builders . update . addBlock ( deindent `
60
- var ${ name } _value = ${ snippet } ;
86
+ if ( node . key ) {
87
+ generator . current . builders . update . addBlock ( deindent `
88
+ var ${ name } _value = ${ snippet } ;
89
+ var _${ name } _iterations = [];
90
+ var _${ name } _lookup = Object.create( null );
91
+
92
+ var ${ localVars . fragment } = document.createDocumentFragment();
93
+
94
+ // create new iterations as necessary
95
+ for ( var ${ i } = 0; ${ i } < ${ name } _value.length; ${ i } += 1 ) {
96
+ var ${ localVars . value } = ${ name } _value[${ i } ];
97
+ var ${ localVars . key } = ${ localVars . value } .${ node . key } ;
98
+
99
+ if ( ${ name } _lookup[ ${ localVars . key } ] ) {
100
+ _${ name } _iterations[${ i } ] = _${ name } _lookup[ ${ localVars . key } ] = ${ name } _lookup[ ${ localVars . key } ];
101
+ _${ name } _lookup[ ${ localVars . key } ].update( changed, ${ params } , ${ listName } , ${ listName } [${ i } ], ${ i } );
102
+ } else {
103
+ _${ name } _iterations[${ i } ] = _${ name } _lookup[ ${ localVars . key } ] = ${ renderer } ( ${ params } , ${ listName } , ${ listName } [${ i } ], ${ i } , component${ node . key ? `, ${ localVars . key } ` : `` } );
104
+ }
61
105
62
- for ( var ${ i } = 0; ${ i } < ${ name } _value.length; ${ i } += 1 ) {
63
- if ( !${ iterations } [${ i } ] ) {
64
- ${ iterations } [${ i } ] = ${ renderer } ( ${ params } , ${ listName } , ${ listName } [${ i } ], ${ i } , component );
65
- ${ iterations } [${ i } ].mount( ${ anchor } .parentNode, ${ anchor } );
66
- } else {
67
- ${ iterations } [${ i } ].update( changed, ${ params } , ${ listName } , ${ listName } [${ i } ], ${ i } );
106
+ _${ name } _iterations[${ i } ].mount( ${ localVars . fragment } , null );
68
107
}
69
- }
70
108
71
- for ( var ${ i } = ${ name } _value.length; ${ i } < ${ iterations } .length; ${ i } += 1 ) {
72
- ${ iterations } [${ i } ].teardown( true );
73
- }
109
+ // remove old iterations
110
+ for ( var ${ i } = 0; ${ i } < ${ name } _iterations.length; ${ i } += 1 ) {
111
+ var ${ name } _iteration = ${ name } _iterations[${ i } ];
112
+ if ( !_${ name } _lookup[ ${ name } _iteration.${ localVars . key } ] ) {
113
+ ${ name } _iteration.teardown( true );
114
+ }
115
+ }
74
116
75
- ${ iterations } .length = ${ listName } .length;
76
- ` ) ;
117
+ ${ name } _anchor.parentNode.insertBefore( ${ localVars . fragment } , ${ name } _anchor );
118
+
119
+ ${ name } _iterations = _${ name } _iterations;
120
+ ${ name } _lookup = _${ name } _lookup;
121
+ ` ) ;
122
+ } else {
123
+ generator . current . builders . update . addBlock ( deindent `
124
+ var ${ name } _value = ${ snippet } ;
125
+
126
+ for ( var ${ i } = 0; ${ i } < ${ name } _value.length; ${ i } += 1 ) {
127
+ if ( !${ iterations } [${ i } ] ) {
128
+ ${ iterations } [${ i } ] = ${ renderer } ( ${ params } , ${ listName } , ${ listName } [${ i } ], ${ i } , component );
129
+ ${ iterations } [${ i } ].mount( ${ anchor } .parentNode, ${ anchor } );
130
+ } else {
131
+ ${ iterations } [${ i } ].update( changed, ${ params } , ${ listName } , ${ listName } [${ i } ], ${ i } );
132
+ }
133
+ }
134
+
135
+ for ( var ${ i } = ${ name } _value.length; ${ i } < ${ iterations } .length; ${ i } += 1 ) {
136
+ ${ iterations } [${ i } ].teardown( true );
137
+ }
138
+
139
+ ${ iterations } .length = ${ listName } .length;
140
+ ` ) ;
141
+ }
77
142
78
143
if ( node . else ) {
79
144
generator . current . builders . update . addBlock ( deindent `
@@ -128,6 +193,7 @@ export default {
128
193
target : 'target' ,
129
194
expression : node . expression ,
130
195
context : node . context ,
196
+ key : node . key ,
131
197
localElementDepth : 0 ,
132
198
133
199
contextDependencies,
0 commit comments