feat(compiler-core/v-model): avoid patching v-model handler when possible
This commit is contained in:
@@ -193,21 +193,21 @@ export function buildProps(
|
||||
const analyzePatchFlag = ({ key, value }: Property) => {
|
||||
if (key.type === NodeTypes.SIMPLE_EXPRESSION && key.isStatic) {
|
||||
if (
|
||||
value.type !== NodeTypes.SIMPLE_EXPRESSION ||
|
||||
// E.g: <p :foo="1 + 2" />.
|
||||
// Do not add prop `foo` to `dynamicPropNames`.
|
||||
(!value.isStatic && !value.isConstant)
|
||||
(value.type === NodeTypes.SIMPLE_EXPRESSION ||
|
||||
value.type === NodeTypes.COMPOUND_EXPRESSION) &&
|
||||
isStaticNode(value)
|
||||
) {
|
||||
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(name)
|
||||
}
|
||||
return
|
||||
}
|
||||
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(name)
|
||||
}
|
||||
} else {
|
||||
hasDynamicKeys = true
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
import { DirectiveTransform } from '../transform'
|
||||
import { DirectiveTransform, TransformContext } from '../transform'
|
||||
import {
|
||||
createSimpleExpression,
|
||||
createObjectProperty,
|
||||
createCompoundExpression,
|
||||
NodeTypes,
|
||||
Property
|
||||
Property,
|
||||
CompoundExpressionNode,
|
||||
createInterpolation
|
||||
} from '../ast'
|
||||
import { createCompilerError, ErrorCodes } from '../errors'
|
||||
import { isMemberExpression } from '../utils'
|
||||
import { isObject } from '@vue/shared'
|
||||
|
||||
export const transformModel: DirectiveTransform = (dir, node, context) => {
|
||||
const { exp, arg } = dir
|
||||
@@ -38,13 +41,23 @@ export const transformModel: DirectiveTransform = (dir, node, context) => {
|
||||
])
|
||||
: createSimpleExpression('onUpdate:modelValue', true)
|
||||
|
||||
let assignmentChildren =
|
||||
exp.type === NodeTypes.SIMPLE_EXPRESSION ? [exp] : exp.children
|
||||
// For a member expression used in assignment, it only needs to be updated
|
||||
// if the expression involves scope variables. Otherwise we can mark the
|
||||
// expression as constant to avoid it being included in `dynamicPropNames`
|
||||
// of the element. This optimization relies on `prefixIdentifiers: true`.
|
||||
if (!__BROWSER__ && context.prefixIdentifiers) {
|
||||
assignmentChildren = assignmentChildren.map(c => toConstant(c, context))
|
||||
}
|
||||
|
||||
const props = [
|
||||
createObjectProperty(propName, dir.exp!),
|
||||
createObjectProperty(
|
||||
eventName,
|
||||
createCompoundExpression([
|
||||
`$event => (`,
|
||||
...(exp.type === NodeTypes.SIMPLE_EXPRESSION ? [exp] : exp.children),
|
||||
...assignmentChildren,
|
||||
` = $event)`
|
||||
])
|
||||
)
|
||||
@@ -57,6 +70,30 @@ export const transformModel: DirectiveTransform = (dir, node, context) => {
|
||||
return createTransformProps(props)
|
||||
}
|
||||
|
||||
function toConstant(
|
||||
exp: CompoundExpressionNode | CompoundExpressionNode['children'][0],
|
||||
context: TransformContext
|
||||
): any {
|
||||
if (!isObject(exp) || exp.type === NodeTypes.TEXT) {
|
||||
return exp
|
||||
}
|
||||
if (exp.type === NodeTypes.SIMPLE_EXPRESSION) {
|
||||
if (exp.isStatic || context.identifiers[exp.content]) {
|
||||
return exp
|
||||
}
|
||||
return {
|
||||
...exp,
|
||||
isConstant: true
|
||||
}
|
||||
} else if (exp.type === NodeTypes.COMPOUND_EXPRESSION) {
|
||||
return createCompoundExpression(
|
||||
exp.children.map(c => toConstant(c, context))
|
||||
)
|
||||
} else if (exp.type === NodeTypes.INTERPOLATION) {
|
||||
return createInterpolation(toConstant(exp.content, context), exp.loc)
|
||||
}
|
||||
}
|
||||
|
||||
function createTransformProps(props: Property[] = []) {
|
||||
return { props, needRuntime: false }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user