feat: support v-bind .prop & .attr modifiers
Also allows render function usage like the following:
```js
h({
'.prop': 1, // force set as property
'^attr': 'foo' // force set as attribute
})
```
This commit is contained in:
@@ -1276,6 +1276,54 @@ describe('compiler: parse', () => {
|
||||
})
|
||||
})
|
||||
|
||||
test('v-bind .prop shorthand', () => {
|
||||
const ast = baseParse('<div .a=b />')
|
||||
const directive = (ast.children[0] as ElementNode).props[0]
|
||||
|
||||
expect(directive).toStrictEqual({
|
||||
type: NodeTypes.DIRECTIVE,
|
||||
name: 'bind',
|
||||
arg: {
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: 'a',
|
||||
isStatic: true,
|
||||
constType: ConstantTypes.CAN_STRINGIFY,
|
||||
|
||||
loc: {
|
||||
source: 'a',
|
||||
start: {
|
||||
column: 7,
|
||||
line: 1,
|
||||
offset: 6
|
||||
},
|
||||
end: {
|
||||
column: 8,
|
||||
line: 1,
|
||||
offset: 7
|
||||
}
|
||||
}
|
||||
},
|
||||
modifiers: ['prop'],
|
||||
exp: {
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: 'b',
|
||||
isStatic: false,
|
||||
constType: ConstantTypes.NOT_CONSTANT,
|
||||
|
||||
loc: {
|
||||
start: { offset: 8, line: 1, column: 9 },
|
||||
end: { offset: 9, line: 1, column: 10 },
|
||||
source: 'b'
|
||||
}
|
||||
},
|
||||
loc: {
|
||||
start: { offset: 5, line: 1, column: 6 },
|
||||
end: { offset: 9, line: 1, column: 10 },
|
||||
source: '.a=b'
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
test('v-bind shorthand with modifier', () => {
|
||||
const ast = baseParse('<div :a.sync=b />')
|
||||
const directive = (ast.children[0] as ElementNode).props[0]
|
||||
|
||||
@@ -172,22 +172,140 @@ describe('compiler: transform v-bind', () => {
|
||||
const node = parseWithVBind(`<div v-bind:[foo(bar)].camel="id"/>`, {
|
||||
prefixIdentifiers: true
|
||||
})
|
||||
const props = (node.codegenNode as VNodeCall).props as CallExpression
|
||||
expect(props).toMatchObject({
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: NORMALIZE_PROPS,
|
||||
arguments: [
|
||||
{
|
||||
type: NodeTypes.JS_OBJECT_EXPRESSION,
|
||||
properties: [
|
||||
{
|
||||
key: {
|
||||
children: [
|
||||
`_${helperNameMap[CAMELIZE]}(`,
|
||||
`(`,
|
||||
{ content: `_ctx.foo` },
|
||||
`(`,
|
||||
{ content: `_ctx.bar` },
|
||||
`)`,
|
||||
`) || ""`,
|
||||
`)`
|
||||
]
|
||||
},
|
||||
value: {
|
||||
content: `_ctx.id`,
|
||||
isStatic: false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
})
|
||||
})
|
||||
|
||||
test('.prop modifier', () => {
|
||||
const node = parseWithVBind(`<div v-bind:fooBar.prop="id"/>`)
|
||||
const props = (node.codegenNode as VNodeCall).props as ObjectExpression
|
||||
expect(props.properties[0]).toMatchObject({
|
||||
key: {
|
||||
children: [
|
||||
`_${helperNameMap[CAMELIZE]}(`,
|
||||
`(`,
|
||||
{ content: `_ctx.foo` },
|
||||
`(`,
|
||||
{ content: `_ctx.bar` },
|
||||
`)`,
|
||||
`) || ""`,
|
||||
`)`
|
||||
]
|
||||
content: `.fooBar`,
|
||||
isStatic: true
|
||||
},
|
||||
value: {
|
||||
content: `_ctx.id`,
|
||||
content: `id`,
|
||||
isStatic: false
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
test('.prop modifier w/ dynamic arg', () => {
|
||||
const node = parseWithVBind(`<div v-bind:[fooBar].prop="id"/>`)
|
||||
const props = (node.codegenNode as VNodeCall).props as CallExpression
|
||||
expect(props).toMatchObject({
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: NORMALIZE_PROPS,
|
||||
arguments: [
|
||||
{
|
||||
type: NodeTypes.JS_OBJECT_EXPRESSION,
|
||||
properties: [
|
||||
{
|
||||
key: {
|
||||
content: '`.${fooBar || ""}`',
|
||||
isStatic: false
|
||||
},
|
||||
value: {
|
||||
content: `id`,
|
||||
isStatic: false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
})
|
||||
})
|
||||
|
||||
test('.prop modifier w/ dynamic arg + prefixIdentifiers', () => {
|
||||
const node = parseWithVBind(`<div v-bind:[foo(bar)].prop="id"/>`, {
|
||||
prefixIdentifiers: true
|
||||
})
|
||||
const props = (node.codegenNode as VNodeCall).props as CallExpression
|
||||
expect(props).toMatchObject({
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: NORMALIZE_PROPS,
|
||||
arguments: [
|
||||
{
|
||||
type: NodeTypes.JS_OBJECT_EXPRESSION,
|
||||
properties: [
|
||||
{
|
||||
key: {
|
||||
children: [
|
||||
`'.' + (`,
|
||||
`(`,
|
||||
{ content: `_ctx.foo` },
|
||||
`(`,
|
||||
{ content: `_ctx.bar` },
|
||||
`)`,
|
||||
`) || ""`,
|
||||
`)`
|
||||
]
|
||||
},
|
||||
value: {
|
||||
content: `_ctx.id`,
|
||||
isStatic: false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
})
|
||||
})
|
||||
|
||||
test('.prop modifier (shorthand)', () => {
|
||||
const node = parseWithVBind(`<div .fooBar="id"/>`)
|
||||
const props = (node.codegenNode as VNodeCall).props as ObjectExpression
|
||||
expect(props.properties[0]).toMatchObject({
|
||||
key: {
|
||||
content: `.fooBar`,
|
||||
isStatic: true
|
||||
},
|
||||
value: {
|
||||
content: `id`,
|
||||
isStatic: false
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
test('.attr modifier', () => {
|
||||
const node = parseWithVBind(`<div v-bind:foo-bar.attr="id"/>`)
|
||||
const props = (node.codegenNode as VNodeCall).props as ObjectExpression
|
||||
expect(props.properties[0]).toMatchObject({
|
||||
key: {
|
||||
content: `^foo-bar`,
|
||||
isStatic: true
|
||||
},
|
||||
value: {
|
||||
content: `id`,
|
||||
isStatic: false
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user