Skip to content

Commit

Permalink
feat: support usage of v-once with v-if (#200)
Browse files Browse the repository at this point in the history
Co-authored-by: 三咲智子 Kevin Deng <[email protected]>
  • Loading branch information
lulu0119 and sxzz committed May 12, 2024
1 parent 75314f2 commit b3cb392
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,33 @@ export function render(_ctx) {
return n1
}"
`;

exports[`compiler: v-once > with v-if 1`] = `
"import { createIf as _createIf, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = _createIf(() => (_ctx.expr), () => {
const n2 = t0()
return n2
}, null, true)
return n0
}"
`;

exports[`compiler: v-once > with v-if/else 1`] = `
"import { createIf as _createIf, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
const t1 = _template("<p></p>")
export function render(_ctx) {
const n0 = _createIf(() => (_ctx.expr), () => {
const n2 = t0()
return n2
}, () => {
const n4 = t1()
return n4
}, true)
return n0
}"
`;
60 changes: 59 additions & 1 deletion packages/compiler-vapor/__tests__/transforms/vOnce.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,64 @@ describe('compiler: v-once', () => {
})

test.todo('with hoistStatic: true')
test.todo('with v-if/else')

test('with v-if', () => {
const { ir, code, helpers } = compileWithOnce(`<div v-if="expr" v-once />`)
expect(code).toMatchSnapshot()
expect(helpers).lengthOf(0)
expect(ir.block.effect).lengthOf(0)
expect(ir.block.operation).toMatchObject([
{
type: IRNodeTypes.IF,
id: 0,
once: true,
condition: {
type: NodeTypes.SIMPLE_EXPRESSION,
content: 'expr',
isStatic: false,
},
positive: {
type: IRNodeTypes.BLOCK,
dynamic: {
children: [{ template: 0 }],
},
},
},
])
})

test('with v-if/else', () => {
const { ir, code, helpers } = compileWithOnce(
`<div v-if="expr" v-once /><p v-else/>`,
)
expect(code).toMatchSnapshot()
expect(helpers).lengthOf(0)
expect(ir.block.effect).lengthOf(0)
expect(ir.block.operation).toMatchObject([
{
type: IRNodeTypes.IF,
id: 0,
once: true,
condition: {
type: NodeTypes.SIMPLE_EXPRESSION,
content: 'expr',
isStatic: false,
},
positive: {
type: IRNodeTypes.BLOCK,
dynamic: {
children: [{ template: 0 }],
},
},
negative: {
type: IRNodeTypes.BLOCK,
dynamic: {
children: [{ template: 1 }],
},
},
},
])
})

test.todo('with v-for')
})
5 changes: 3 additions & 2 deletions packages/compiler-vapor/src/generators/if.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export function genIf(
isNested = false,
): CodeFragment[] {
const { vaporHelper } = context
const { condition, positive, negative } = oper
const { condition, positive, negative, once } = oper
const [frag, push] = buildCodeFragment()

const conditionExpr: CodeFragment[] = [
Expand All @@ -36,7 +36,8 @@ export function genIf(
vaporHelper('createIf'),
conditionExpr,
positiveArg,
negativeArg,
negativeArg || (once ? 'null' : false),
once && 'true',
),
)

Expand Down
1 change: 1 addition & 0 deletions packages/compiler-vapor/src/ir.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ export interface IfIRNode extends BaseIRNode {
condition: SimpleExpressionNode
positive: BlockIRNode
negative?: BlockIRNode | IfIRNode
once?: boolean
}

export interface ForIRNode extends BaseIRNode {
Expand Down
2 changes: 2 additions & 0 deletions packages/compiler-vapor/src/transforms/vIf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export function processIf(
id,
condition: dir.exp!,
positive: branch,
once: context.inVOnce,
})
}
} else {
Expand Down Expand Up @@ -101,6 +102,7 @@ export function processIf(
id: -1,
condition: dir.exp!,
positive: branch,
once: context.inVOnce,
}
}

Expand Down
11 changes: 9 additions & 2 deletions packages/runtime-vapor/src/apiCreateIf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export const createIf = (
condition: () => any,
b1: BlockFn,
b2?: BlockFn,
once?: boolean,
// hydrationNode?: Node,
): Fragment => {
let newValue: any
Expand All @@ -31,7 +32,13 @@ export const createIf = (
// setCurrentHydrationNode(hydrationNode!)
// }

renderEffect(() => {
if (once) {
doIf()
} else {
renderEffect(() => doIf())
}

function doIf() {
if ((newValue = !!condition()) !== oldValue) {
parent ||= anchor.parentNode
if (block) {
Expand All @@ -47,7 +54,7 @@ export const createIf = (
fragment.nodes = []
}
}
})
}

// TODO: SSR
// if (isHydrating) {
Expand Down

0 comments on commit b3cb392

Please sign in to comment.