mirror of https://github.com/vuejs/core.git
fix(compiler-vapor): treat attribute as dynamic if has dynamic key prop
This commit is contained in:
parent
6d098b6871
commit
2229d3ce20
|
@ -169,6 +169,20 @@ export function render(_ctx) {
|
||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`compiler v-bind > dynamic arg w/ static attribute 1`] = `
|
||||||
|
"import { template as _template, children as _children, renderEffect as _renderEffect, setDynamicProps as _setDynamicProps } from 'vue/vapor';
|
||||||
|
|
||||||
|
export function render(_ctx) {
|
||||||
|
const t0 = _template("<div></div>")
|
||||||
|
const n0 = t0()
|
||||||
|
const { 0: [n1],} = _children(n0)
|
||||||
|
_renderEffect(() => {
|
||||||
|
_setDynamicProps(n1, { [_ctx.id]: _ctx.id, foo: "bar", checked: "" })
|
||||||
|
})
|
||||||
|
return n0
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`compiler v-bind > no expression (shorthand) 1`] = `
|
exports[`compiler v-bind > no expression (shorthand) 1`] = `
|
||||||
"import { template as _template, children as _children, renderEffect as _renderEffect, setDynamicProp as _setDynamicProp } from 'vue/vapor';
|
"import { template as _template, children as _children, renderEffect as _renderEffect, setDynamicProp as _setDynamicProp } from 'vue/vapor';
|
||||||
|
|
||||||
|
|
|
@ -167,6 +167,55 @@ describe('compiler v-bind', () => {
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('dynamic arg w/ static attribute', () => {
|
||||||
|
const { ir, code } = compileWithVBind(
|
||||||
|
`<div v-bind:[id]="id" foo="bar" checked />`,
|
||||||
|
)
|
||||||
|
expect(code).matchSnapshot()
|
||||||
|
expect(ir.effect[0].operations[0]).toMatchObject({
|
||||||
|
type: IRNodeTypes.SET_DYNAMIC_PROPS,
|
||||||
|
element: 1,
|
||||||
|
props: [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
key: {
|
||||||
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
|
content: 'id',
|
||||||
|
isStatic: false,
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
|
content: 'id',
|
||||||
|
isStatic: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: {
|
||||||
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
|
content: 'foo',
|
||||||
|
isStatic: true,
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
|
content: 'bar',
|
||||||
|
isStatic: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: {
|
||||||
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
|
content: 'checked',
|
||||||
|
isStatic: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
],
|
||||||
|
})
|
||||||
|
expect(code).contains(
|
||||||
|
'_setDynamicProps(n1, { [_ctx.id]: _ctx.id, foo: "bar", checked: "" })',
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
test('should error if empty expression', () => {
|
test('should error if empty expression', () => {
|
||||||
const onError = vi.fn()
|
const onError = vi.fn()
|
||||||
const { ir, code } = compileWithVBind(`<div v-bind:arg="" />`, {
|
const { ir, code } = compileWithVBind(`<div v-bind:arg="" />`, {
|
||||||
|
|
|
@ -10,7 +10,6 @@ import {
|
||||||
type ParentNode,
|
type ParentNode,
|
||||||
type RootNode,
|
type RootNode,
|
||||||
type SimpleExpressionNode,
|
type SimpleExpressionNode,
|
||||||
type SourceLocation,
|
|
||||||
type TemplateChildNode,
|
type TemplateChildNode,
|
||||||
type TemplateNode,
|
type TemplateNode,
|
||||||
defaultOnError,
|
defaultOnError,
|
||||||
|
@ -46,7 +45,6 @@ export type DirectiveTransform = (
|
||||||
export interface DirectiveTransformResult {
|
export interface DirectiveTransformResult {
|
||||||
key: SimpleExpressionNode
|
key: SimpleExpressionNode
|
||||||
value: SimpleExpressionNode
|
value: SimpleExpressionNode
|
||||||
loc: SourceLocation
|
|
||||||
modifier?: '.' | '^'
|
modifier?: '.' | '^'
|
||||||
runtimeCamelize?: boolean
|
runtimeCamelize?: boolean
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import {
|
||||||
NodeTypes,
|
NodeTypes,
|
||||||
type SimpleExpressionNode,
|
type SimpleExpressionNode,
|
||||||
createCompilerError,
|
createCompilerError,
|
||||||
|
createSimpleExpression,
|
||||||
} from '@vue/compiler-dom'
|
} from '@vue/compiler-dom'
|
||||||
import { isBuiltInDirective, isReservedProp, isVoidTag } from '@vue/shared'
|
import { isBuiltInDirective, isReservedProp, isVoidTag } from '@vue/shared'
|
||||||
import type {
|
import type {
|
||||||
|
@ -57,16 +58,18 @@ export const transformElement: NodeTransform = (node, context) => {
|
||||||
function buildProps(
|
function buildProps(
|
||||||
node: ElementNode,
|
node: ElementNode,
|
||||||
context: TransformContext<ElementNode>,
|
context: TransformContext<ElementNode>,
|
||||||
props: ElementNode['props'] = node.props,
|
props: (VaporDirectiveNode | AttributeNode)[] = node.props as any,
|
||||||
isComponent: boolean,
|
isComponent: boolean,
|
||||||
) {
|
) {
|
||||||
const dynamicArgs: PropsExpression[] = []
|
const dynamicArgs: PropsExpression[] = []
|
||||||
const dynamicExpr: SimpleExpressionNode[] = []
|
const dynamicExpr: SimpleExpressionNode[] = []
|
||||||
let results: DirectiveTransformResult[] = []
|
let results: DirectiveTransformResult[] = []
|
||||||
|
|
||||||
function pushExpressions(...exprs: SimpleExpressionNode[]) {
|
function pushDynamicExpressions(
|
||||||
|
...exprs: (SimpleExpressionNode | undefined)[]
|
||||||
|
) {
|
||||||
for (const expr of exprs) {
|
for (const expr of exprs) {
|
||||||
if (!expr.isStatic) dynamicExpr.push(expr)
|
if (expr && !expr.isStatic) dynamicExpr.push(expr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,14 +80,22 @@ function buildProps(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const prop of props as (VaporDirectiveNode | AttributeNode)[]) {
|
// treat all props as dynamic key
|
||||||
|
const asDynamic = props.some(
|
||||||
|
prop =>
|
||||||
|
prop.type === NodeTypes.DIRECTIVE &&
|
||||||
|
prop.name === 'bind' &&
|
||||||
|
(!prop.arg || !prop.arg.isStatic),
|
||||||
|
)
|
||||||
|
|
||||||
|
for (const prop of props) {
|
||||||
if (
|
if (
|
||||||
prop.type === NodeTypes.DIRECTIVE &&
|
prop.type === NodeTypes.DIRECTIVE &&
|
||||||
prop.name === 'bind' &&
|
prop.name === 'bind' &&
|
||||||
!prop.arg
|
!prop.arg
|
||||||
) {
|
) {
|
||||||
if (prop.exp) {
|
if (prop.exp) {
|
||||||
pushExpressions(prop.exp)
|
pushDynamicExpressions(prop.exp)
|
||||||
pushMergeArg()
|
pushMergeArg()
|
||||||
dynamicArgs.push(prop.exp)
|
dynamicArgs.push(prop.exp)
|
||||||
} else {
|
} else {
|
||||||
|
@ -95,10 +106,10 @@ function buildProps(
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = transformProp(prop, node, context)
|
const result = transformProp(prop, node, context, asDynamic)
|
||||||
if (result) {
|
if (result) {
|
||||||
results.push(result)
|
results.push(result)
|
||||||
pushExpressions(result.key, result.value)
|
asDynamic && pushDynamicExpressions(result.key, result.value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,15 +147,27 @@ function transformProp(
|
||||||
prop: VaporDirectiveNode | AttributeNode,
|
prop: VaporDirectiveNode | AttributeNode,
|
||||||
node: ElementNode,
|
node: ElementNode,
|
||||||
context: TransformContext<ElementNode>,
|
context: TransformContext<ElementNode>,
|
||||||
|
asDynamic: boolean,
|
||||||
): DirectiveTransformResult | void {
|
): DirectiveTransformResult | void {
|
||||||
const { name } = prop
|
const { name } = prop
|
||||||
if (isReservedProp(name)) return
|
if (isReservedProp(name)) return
|
||||||
|
|
||||||
if (prop.type === NodeTypes.ATTRIBUTE) {
|
if (prop.type === NodeTypes.ATTRIBUTE) {
|
||||||
|
if (asDynamic) {
|
||||||
|
return {
|
||||||
|
key: createSimpleExpression(prop.name, true, prop.nameLoc),
|
||||||
|
value: createSimpleExpression(
|
||||||
|
prop.value ? prop.value.content : '',
|
||||||
|
true,
|
||||||
|
prop.value && prop.value.loc,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
context.template += ` ${name}`
|
context.template += ` ${name}`
|
||||||
if (prop.value) context.template += `="${prop.value.content}"`
|
if (prop.value) context.template += `="${prop.value.content}"`
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const directiveTransform = context.options.directiveTransforms[name]
|
const directiveTransform = context.options.directiveTransforms[name]
|
||||||
if (directiveTransform) {
|
if (directiveTransform) {
|
||||||
|
|
Loading…
Reference in New Issue