@@ -3,21 +3,17 @@ import {
|
||||
transform,
|
||||
NodeTypes,
|
||||
generate,
|
||||
CompilerOptions
|
||||
CompilerOptions,
|
||||
getBaseTransformPreset
|
||||
} from '../../src'
|
||||
import { transformOnce } from '../../src/transforms/vOnce'
|
||||
import { transformElement } from '../../src/transforms/transformElement'
|
||||
import { RENDER_SLOT, SET_BLOCK_TRACKING } from '../../src/runtimeHelpers'
|
||||
import { transformBind } from '../../src/transforms/vBind'
|
||||
import { transformSlotOutlet } from '../../src/transforms/transformSlotOutlet'
|
||||
|
||||
function transformWithOnce(template: string, options: CompilerOptions = {}) {
|
||||
const ast = parse(template)
|
||||
const [nodeTransforms, directiveTransforms] = getBaseTransformPreset()
|
||||
transform(ast, {
|
||||
nodeTransforms: [transformOnce, transformElement, transformSlotOutlet],
|
||||
directiveTransforms: {
|
||||
bind: transformBind
|
||||
},
|
||||
nodeTransforms,
|
||||
directiveTransforms,
|
||||
...options
|
||||
})
|
||||
return ast
|
||||
@@ -102,4 +98,30 @@ describe('compiler: v-once transform', () => {
|
||||
})
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
||||
test('with v-if', () => {
|
||||
const root = transformWithOnce(`<div v-if="true" v-once />`)
|
||||
expect(root.cached).toBe(1)
|
||||
expect(root.helpers).toContain(SET_BLOCK_TRACKING)
|
||||
expect(root.children[0]).toMatchObject({
|
||||
type: NodeTypes.IF,
|
||||
// should cache the entire v-if expression, not just a single branch
|
||||
codegenNode: {
|
||||
type: NodeTypes.JS_CACHE_EXPRESSION
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
test('with v-for', () => {
|
||||
const root = transformWithOnce(`<div v-for="i in list" v-once />`)
|
||||
expect(root.cached).toBe(1)
|
||||
expect(root.helpers).toContain(SET_BLOCK_TRACKING)
|
||||
expect(root.children[0]).toMatchObject({
|
||||
type: NodeTypes.FOR,
|
||||
// should cache the entire v-for expression, not just a single branch
|
||||
codegenNode: {
|
||||
type: NodeTypes.JS_CACHE_EXPRESSION
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -399,6 +399,7 @@ export function traverseNode(
|
||||
}
|
||||
|
||||
// exit transforms
|
||||
context.currentNode = node
|
||||
let i = exitFns.length
|
||||
while (i--) {
|
||||
exitFns[i]()
|
||||
|
||||
@@ -1,14 +1,21 @@
|
||||
import { NodeTransform } from '../transform'
|
||||
import { findDir } from '../utils'
|
||||
import { NodeTypes } from '../ast'
|
||||
import { ElementNode, ForNode, IfNode, NodeTypes } from '../ast'
|
||||
import { SET_BLOCK_TRACKING } from '../runtimeHelpers'
|
||||
|
||||
const seen = new WeakSet()
|
||||
|
||||
export const transformOnce: NodeTransform = (node, context) => {
|
||||
if (node.type === NodeTypes.ELEMENT && findDir(node, 'once', true)) {
|
||||
if (seen.has(node)) {
|
||||
return
|
||||
}
|
||||
seen.add(node)
|
||||
context.helper(SET_BLOCK_TRACKING)
|
||||
return () => {
|
||||
if (node.codegenNode) {
|
||||
node.codegenNode = context.cache(node.codegenNode, true /* isVNode */)
|
||||
const cur = context.currentNode as ElementNode | IfNode | ForNode
|
||||
if (cur.codegenNode) {
|
||||
cur.codegenNode = context.cache(cur.codegenNode, true /* isVNode */)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user