refactor(compiler-vapor): group directives by same element

This commit is contained in:
三咲智子 Kevin Deng 2024-01-27 20:49:43 +08:00
parent 0255505b5d
commit c2c8070207
No known key found for this signature in database
GPG Key ID: 69992F2250DFD93E
4 changed files with 77 additions and 42 deletions

View File

@ -16,6 +16,18 @@ export function render(_ctx) {
}" }"
`; `;
exports[`compile > custom directive > basic 1`] = `
"import { template as _template, children as _children, withDirectives as _withDirectives, resolveDirective("vTest") as _resolveDirective("vTest"), resolveDirective("vHello") as _resolveDirective("vHello") } from 'vue/vapor';
export function render(_ctx) {
const t0 = _template("<div></div>")
const n0 = t0()
const { 0: [n1],} = _children(n0)
_withDirectives(n1, [[_resolveDirective("vTest")], [_resolveDirective("vHello"), void 0, void 0, { world: true }]])
return n0
}"
`;
exports[`compile > directives > custom directive > basic 1`] = ` exports[`compile > directives > custom directive > basic 1`] = `
"import { template as _template, children as _children, withDirectives as _withDirectives } from 'vue/vapor'; "import { template as _template, children as _children, withDirectives as _withDirectives } from 'vue/vapor';

View File

@ -207,4 +207,11 @@ describe('compile', () => {
// TODO: add more test for expression parsing (v-on, v-slot, v-for) // TODO: add more test for expression parsing (v-on, v-slot, v-for)
}) })
describe('custom directive', () => {
test('basic', () => {
const code = compile(`<div v-test v-hello.world />`)
expect(code).matchSnapshot()
})
})
}) })

View File

@ -281,11 +281,12 @@ export function generate(
) )
} }
for (const oper of ir.operation.filter( const directiveOps = ir.operation.filter(
(oper): oper is WithDirectiveIRNode => (oper): oper is WithDirectiveIRNode =>
oper.type === IRNodeTypes.WITH_DIRECTIVE, oper.type === IRNodeTypes.WITH_DIRECTIVE,
)) { )
genWithDirective(oper, ctx) for (const directives of groupDirective(directiveOps)) {
genWithDirective(directives, ctx)
} }
for (const operation of ir.operation) { for (const operation of ir.operation) {
@ -393,3 +394,12 @@ function genOperation(oper: OperationNode, context: CodegenContext) {
return checkNever(oper) return checkNever(oper)
} }
} }
function groupDirective(ops: WithDirectiveIRNode[]): WithDirectiveIRNode[][] {
const directiveMap: Record<number, WithDirectiveIRNode[]> = {}
for (const oper of ops) {
if (!directiveMap[oper.element]) directiveMap[oper.element] = []
directiveMap[oper.element].push(oper)
}
return Object.values(directiveMap)
}

View File

@ -5,61 +5,67 @@ import type { CodegenContext } from '../generate'
import type { WithDirectiveIRNode } from '../ir' import type { WithDirectiveIRNode } from '../ir'
export function genWithDirective( export function genWithDirective(
oper: WithDirectiveIRNode, opers: WithDirectiveIRNode[],
context: CodegenContext, context: CodegenContext,
) { ) {
const { push, newline, pushFnCall, pushMulti, vaporHelper, bindingMetadata } = const { push, newline, pushFnCall, pushMulti, vaporHelper, bindingMetadata } =
context context
const { dir, builtin } = oper
// TODO merge directive for the same node
newline() newline()
pushFnCall( pushFnCall(
vaporHelper('withDirectives'), vaporHelper('withDirectives'),
// 1st arg: node // 1st arg: node
`n${oper.element}`, `n${opers[0].element}`,
// 2nd arg: directives // 2nd arg: directives
() => { () => {
push('[')
// directive // directive
pushMulti(['[', ']', ', '], () => { pushMulti(
if (dir.name === 'show') { ['[', ']', ', '],
push(vaporHelper('vShow')) ...opers.map((oper) => () => {
} else if (builtin) { push('[')
push(vaporHelper(builtin))
} else { const { dir, builtin } = oper
const directiveReference = camelize(`v-${dir.name}`) if (dir.name === 'show') {
// TODO resolve directive push(vaporHelper('vShow'))
if (bindingMetadata[directiveReference]) { } else if (builtin) {
const directiveExpression = push(vaporHelper(builtin))
createSimpleExpression(directiveReference) } else {
directiveExpression.ast = null const directiveReference = camelize(`v-${dir.name}`)
genExpression(directiveExpression, context) // TODO resolve directive
if (bindingMetadata[directiveReference]) {
const directiveExpression =
createSimpleExpression(directiveReference)
directiveExpression.ast = null
genExpression(directiveExpression, context)
} else {
push(vaporHelper(`resolveDirective("${directiveReference}")`))
}
} }
}
if (dir.exp) { if (dir.exp) {
push(', () => ') push(', () => ')
genExpression(dir.exp, context) genExpression(dir.exp, context)
} else if (dir.arg || dir.modifiers.length) { } else if (dir.arg || dir.modifiers.length) {
push(', void 0') push(', void 0')
} }
if (dir.arg) { if (dir.arg) {
push(', ') push(', ')
genExpression(dir.arg, context) genExpression(dir.arg, context)
} else if (dir.modifiers.length) { } else if (dir.modifiers.length) {
push(', void 0') push(', void 0')
} }
if (dir.modifiers.length) { if (dir.modifiers.length) {
push(', ') push(', ')
push('{ ') push('{ ')
push(genDirectiveModifiers(dir.modifiers)) push(genDirectiveModifiers(dir.modifiers))
push(' }') push(' }')
} }
})
push(']') push(']')
}),
)
}, },
) )
} }