fix(compiler): patchFlag analysis should factor in props returned by directive transforms

This commit is contained in:
Evan You 2019-10-04 08:37:10 -04:00
parent 095f5edf8d
commit 6059fe69e8
2 changed files with 34 additions and 37 deletions

View File

@ -292,18 +292,20 @@ describe('compiler: element transform', () => {
} }
] ]
}) })
// should factor in props returned by custom directive transforms
// in patchFlag analysis
expect(node.arguments[3]).toMatch(PatchFlags.PROPS + '')
expect(node.arguments[4]).toMatch(`"bar"`)
}) })
test('directiveTransform with needRuntime: true', () => { test('directiveTransform with needRuntime: true', () => {
let _dir: DirectiveNode
const { root, node } = parseWithElementTransform( const { root, node } = parseWithElementTransform(
`<div v-foo:bar="hello" />`, `<div v-foo:bar="hello" />`,
{ {
directiveTransforms: { directiveTransforms: {
foo(dir) { foo() {
_dir = dir
return { return {
props: [createObjectProperty(dir.arg!, dir.exp!)], props: [],
needRuntime: true needRuntime: true
} }
} }
@ -320,16 +322,7 @@ describe('compiler: element transform', () => {
callee: `_${CREATE_VNODE}`, callee: `_${CREATE_VNODE}`,
arguments: [ arguments: [
`"div"`, `"div"`,
{ `null`,
type: NodeTypes.JS_OBJECT_EXPRESSION,
properties: [
{
type: NodeTypes.JS_PROPERTY,
key: _dir!.arg,
value: _dir!.exp
}
]
},
`null`, `null`,
`${PatchFlags.NEED_PATCH} /* NEED_PATCH */` // should generate appropriate flag `${PatchFlags.NEED_PATCH} /* NEED_PATCH */` // should generate appropriate flag
] ]

View File

@ -185,11 +185,30 @@ export function buildProps(
// patchFlag analysis // patchFlag analysis
let patchFlag = 0 let patchFlag = 0
const dynamicPropNames: string[] = [] let hasRef = false
let hasDynamicKeys = false
let hasClassBinding = false let hasClassBinding = false
let hasStyleBinding = false let hasStyleBinding = false
let hasRef = false let hasDynamicKeys = false
const dynamicPropNames: string[] = []
const anaylizePatchFlag = ({ key, value }: Property) => {
if (key.type === NodeTypes.SIMPLE_EXPRESSION && key.isStatic) {
if (value.type !== NodeTypes.SIMPLE_EXPRESSION || !value.isStatic) {
const name = key.content
if (name === 'ref') {
hasRef = true
} else if (name === 'class') {
hasClassBinding = true
} else if (name === 'style') {
hasStyleBinding = true
} else if (name !== 'key') {
dynamicPropNames.push(key.content)
}
}
} else {
hasDynamicKeys = true
}
}
for (let i = 0; i < props.length; i++) { for (let i = 0; i < props.length; i++) {
// static attribute // static attribute
@ -229,7 +248,8 @@ export function buildProps(
// special case for v-bind and v-on with no argument // special case for v-bind and v-on with no argument
const isBind = name === 'bind' const isBind = name === 'bind'
if (!arg && (isBind || name === 'on')) { const isOn = name === 'on'
if (!arg && (isBind || isOn)) {
hasDynamicKeys = true hasDynamicKeys = true
if (exp) { if (exp) {
if (properties.length) { if (properties.length) {
@ -262,32 +282,16 @@ export function buildProps(
continue continue
} }
// patchFlag analysis
if (isBind && arg) {
if (arg.type === NodeTypes.SIMPLE_EXPRESSION && arg.isStatic) {
const name = arg.content
if (name === 'ref') {
hasRef = true
} else if (name === 'class') {
hasClassBinding = true
} else if (name === 'style') {
hasStyleBinding = true
} else if (name !== 'key') {
dynamicPropNames.push(name)
}
} else {
hasDynamicKeys = true
}
}
const directiveTransform = context.directiveTransforms[name] const directiveTransform = context.directiveTransforms[name]
if (directiveTransform) { if (directiveTransform) {
// has built-in directive transform. // has built-in directive transform.
const { props, needRuntime } = directiveTransform(prop, context) const { props, needRuntime } = directiveTransform(prop, context)
if (isArray(props)) { if (isArray(props)) {
properties.push(...props) properties.push(...props)
properties.forEach(anaylizePatchFlag)
} else { } else {
properties.push(props) properties.push(props)
anaylizePatchFlag(props)
} }
if (needRuntime) { if (needRuntime) {
runtimeDirectives.push(prop) runtimeDirectives.push(prop)
@ -325,7 +329,7 @@ export function buildProps(
) )
} }
// determine the flags to add // patchFlag analysis
if (hasDynamicKeys) { if (hasDynamicKeys) {
patchFlag |= PatchFlags.FULL_PROPS patchFlag |= PatchFlags.FULL_PROPS
} else { } else {