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', () => {
let _dir: DirectiveNode
const { root, node } = parseWithElementTransform(
`<div v-foo:bar="hello" />`,
{
directiveTransforms: {
foo(dir) {
_dir = dir
foo() {
return {
props: [createObjectProperty(dir.arg!, dir.exp!)],
props: [],
needRuntime: true
}
}
@ -320,16 +322,7 @@ describe('compiler: element transform', () => {
callee: `_${CREATE_VNODE}`,
arguments: [
`"div"`,
{
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
]

View File

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