1
1
/* istanbul ignore file */
2
2
3
3
import { DIRECTIVE_PREFIX } from '../../models/generics' ;
4
- import { DirectiveProps } from '../../models/structs' ;
4
+ import { ASTNode , DirectiveProps } from '../../models/structs' ;
5
5
6
6
import compile from '../../core/compile' ;
7
7
import render from '../../core/render' ;
@@ -15,9 +15,9 @@ import computeExpression from '../utils/computeExpression';
15
15
// This directive is size-based, not content-based, since everything is compiled and rerendered
16
16
17
17
export const forDirective = ( { el, data, state, node } : DirectiveProps ) : void => {
18
- const marker = getElementCustomProp ( el , 'component' ) ;
19
-
20
- setElementCustomProp ( el , 'component' , true ) ;
18
+ const originalAST = getElementCustomProp ( el , 'component' ) ;
19
+ // Initial compilation
20
+ if ( ! originalAST ) setElementCustomProp ( el , 'component' , compile ( el , state ) ) ;
21
21
22
22
const forLoopRE = / \s + (?: i n | o f ) \s + / gim;
23
23
const [ expression , target ] = data . value . split ( forLoopRE ) ;
@@ -26,7 +26,6 @@ export const forDirective = ({ el, data, state, node }: DirectiveProps): void =>
26
26
// Try to grab by property, else compute it if it's a custom array
27
27
const currArray =
28
28
( state [ target ?. trim ( ) ] as unknown [ ] ) ?? computeExpression ( target ?. trim ( ) , el , true ) ( state ) ;
29
- const ast = compile ( el , state ) ;
30
29
31
30
const template = getElementCustomProp ( el , '__for_template' ) ;
32
31
if ( el . innerHTML . trim ( ) === template ) el . innerHTML = '' ;
@@ -66,13 +65,16 @@ export const forDirective = ({ el, data, state, node }: DirectiveProps): void =>
66
65
el . appendChild ( isTable ? fragment . firstElementChild . firstElementChild : fragment ) ;
67
66
}
68
67
}
68
+ setElementCustomProp ( el , 'component' , compile ( el , state ) ) ;
69
69
}
70
70
71
- if ( ! marker ) {
71
+ if ( ! originalAST ) {
72
72
// Deps recompiled because child nodes may have additional deps
73
- adjustDeps ( ast , data . deps , node ! , 'for' ) ;
73
+ adjustDeps ( getElementCustomProp ( el , 'component' ) as ASTNode [ ] , data . deps , node ! , 'for' ) ;
74
74
el . removeAttribute ( `${ DIRECTIVE_PREFIX } for` ) ;
75
75
}
76
76
77
- render ( compile ( el , state , true ) , directives , state , node ! . deps ) ;
77
+ // Only recompile if there is no increase/decrease in array size, else use the original AST
78
+ const ast = arrayDiff === 0 ? ( originalAST as ASTNode [ ] ) : compile ( el , state , true ) ;
79
+ render ( ast , directives , state , node ! . deps ) ;
78
80
} ;
0 commit comments