@@ -56,7 +56,7 @@ import {
56
56
toValidAssetId ,
57
57
findProp ,
58
58
isCoreComponent ,
59
- isBindKey ,
59
+ isStaticArgOf ,
60
60
findDir ,
61
61
isStaticExp
62
62
} from '../utils'
@@ -120,10 +120,7 @@ export const transformElement: NodeTransform = (node, context) => {
120
120
// updates inside get proper isSVG flag at runtime. (#639, #643)
121
121
// This is technically web-specific, but splitting the logic out of core
122
122
// leads to too much unnecessary complexity.
123
- ( tag === 'svg' ||
124
- tag === 'foreignObject' ||
125
- // #938: elements with dynamic keys should be forced into blocks
126
- findProp ( node , 'key' , true ) ) )
123
+ ( tag === 'svg' || tag === 'foreignObject' ) )
127
124
128
125
// props
129
126
if ( props . length > 0 ) {
@@ -138,6 +135,10 @@ export const transformElement: NodeTransform = (node, context) => {
138
135
directives . map ( dir => buildDirectiveArgs ( dir , context ) )
139
136
) as DirectiveArguments )
140
137
: undefined
138
+
139
+ if ( propsBuildResult . shouldUseBlock ) {
140
+ shouldUseBlock = true
141
+ }
141
142
}
142
143
143
144
// children
@@ -386,12 +387,15 @@ export function buildProps(
386
387
directives : DirectiveNode [ ]
387
388
patchFlag : number
388
389
dynamicPropNames : string [ ]
390
+ shouldUseBlock : boolean
389
391
} {
390
- const { tag, loc : elementLoc } = node
392
+ const { tag, loc : elementLoc , children } = node
391
393
const isComponent = node . tagType === ElementTypes . COMPONENT
392
394
let properties : ObjectExpression [ 'properties' ] = [ ]
393
395
const mergeArgs : PropsExpression [ ] = [ ]
394
396
const runtimeDirectives : DirectiveNode [ ] = [ ]
397
+ const hasChildren = children . length > 0
398
+ let shouldUseBlock = false
395
399
396
400
// patchFlag analysis
397
401
let patchFlag = 0
@@ -526,7 +530,7 @@ export function buildProps(
526
530
if (
527
531
name === 'is' ||
528
532
( isVBind &&
529
- isBindKey ( arg , 'is' ) &&
533
+ isStaticArgOf ( arg , 'is' ) &&
530
534
( isComponentTag ( tag ) ||
531
535
( __COMPAT__ &&
532
536
isCompatEnabled (
@@ -541,6 +545,16 @@ export function buildProps(
541
545
continue
542
546
}
543
547
548
+ if (
549
+ // #938: elements with dynamic keys should be forced into blocks
550
+ ( isVBind && isStaticArgOf ( arg , 'key' ) ) ||
551
+ // inline before-update hooks need to force block so that it is invoked
552
+ // before children
553
+ ( isVOn && hasChildren && isStaticArgOf ( arg , 'vnodeBeforeUpdate' , true ) )
554
+ ) {
555
+ shouldUseBlock = true
556
+ }
557
+
544
558
// special case for v-bind and v-on with no argument
545
559
if ( ! arg && ( isVBind || isVOn ) ) {
546
560
hasDynamicKeys = true
@@ -633,6 +647,11 @@ export function buildProps(
633
647
} else {
634
648
// no built-in transform, this is a user custom directive.
635
649
runtimeDirectives . push ( prop )
650
+ // custom dirs may use beforeUpdate so they need to force blocks
651
+ // to ensure before-update gets called before children update
652
+ if ( hasChildren ) {
653
+ shouldUseBlock = true
654
+ }
636
655
}
637
656
}
638
657
@@ -700,6 +719,7 @@ export function buildProps(
700
719
}
701
720
}
702
721
if (
722
+ ! shouldUseBlock &&
703
723
( patchFlag === 0 || patchFlag === PatchFlags . HYDRATE_EVENTS ) &&
704
724
( hasRef || hasVnodeHook || runtimeDirectives . length > 0 )
705
725
) {
@@ -784,7 +804,8 @@ export function buildProps(
784
804
props : propsExpression ,
785
805
directives : runtimeDirectives ,
786
806
patchFlag,
787
- dynamicPropNames
807
+ dynamicPropNames,
808
+ shouldUseBlock
788
809
}
789
810
}
790
811
0 commit comments