parent
ad93fa42fc
commit
52e45a9850
@ -3,21 +3,17 @@ import {
|
|||||||
transform,
|
transform,
|
||||||
NodeTypes,
|
NodeTypes,
|
||||||
generate,
|
generate,
|
||||||
CompilerOptions
|
CompilerOptions,
|
||||||
|
getBaseTransformPreset
|
||||||
} from '../../src'
|
} from '../../src'
|
||||||
import { transformOnce } from '../../src/transforms/vOnce'
|
|
||||||
import { transformElement } from '../../src/transforms/transformElement'
|
|
||||||
import { RENDER_SLOT, SET_BLOCK_TRACKING } from '../../src/runtimeHelpers'
|
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 = {}) {
|
function transformWithOnce(template: string, options: CompilerOptions = {}) {
|
||||||
const ast = parse(template)
|
const ast = parse(template)
|
||||||
|
const [nodeTransforms, directiveTransforms] = getBaseTransformPreset()
|
||||||
transform(ast, {
|
transform(ast, {
|
||||||
nodeTransforms: [transformOnce, transformElement, transformSlotOutlet],
|
nodeTransforms,
|
||||||
directiveTransforms: {
|
directiveTransforms,
|
||||||
bind: transformBind
|
|
||||||
},
|
|
||||||
...options
|
...options
|
||||||
})
|
})
|
||||||
return ast
|
return ast
|
||||||
@ -102,4 +98,30 @@ describe('compiler: v-once transform', () => {
|
|||||||
})
|
})
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
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
|
// exit transforms
|
||||||
|
context.currentNode = node
|
||||||
let i = exitFns.length
|
let i = exitFns.length
|
||||||
while (i--) {
|
while (i--) {
|
||||||
exitFns[i]()
|
exitFns[i]()
|
||||||
|
@ -1,14 +1,21 @@
|
|||||||
import { NodeTransform } from '../transform'
|
import { NodeTransform } from '../transform'
|
||||||
import { findDir } from '../utils'
|
import { findDir } from '../utils'
|
||||||
import { NodeTypes } from '../ast'
|
import { ElementNode, ForNode, IfNode, NodeTypes } from '../ast'
|
||||||
import { SET_BLOCK_TRACKING } from '../runtimeHelpers'
|
import { SET_BLOCK_TRACKING } from '../runtimeHelpers'
|
||||||
|
|
||||||
|
const seen = new WeakSet()
|
||||||
|
|
||||||
export const transformOnce: NodeTransform = (node, context) => {
|
export const transformOnce: NodeTransform = (node, context) => {
|
||||||
if (node.type === NodeTypes.ELEMENT && findDir(node, 'once', true)) {
|
if (node.type === NodeTypes.ELEMENT && findDir(node, 'once', true)) {
|
||||||
|
if (seen.has(node)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
seen.add(node)
|
||||||
context.helper(SET_BLOCK_TRACKING)
|
context.helper(SET_BLOCK_TRACKING)
|
||||||
return () => {
|
return () => {
|
||||||
if (node.codegenNode) {
|
const cur = context.currentNode as ElementNode | IfNode | ForNode
|
||||||
node.codegenNode = context.cache(node.codegenNode, true /* isVNode */)
|
if (cur.codegenNode) {
|
||||||
|
cur.codegenNode = context.cache(cur.codegenNode, true /* isVNode */)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { createApp, ref, nextTick } from '../src'
|
import { createApp, ref, nextTick, reactive } from '../src'
|
||||||
|
|
||||||
describe('compiler + runtime integration', () => {
|
describe('compiler + runtime integration', () => {
|
||||||
it('should support runtime template compilation', () => {
|
it('should support runtime template compilation', () => {
|
||||||
@ -247,4 +247,38 @@ describe('compiler + runtime integration', () => {
|
|||||||
|
|
||||||
document.querySelector = origin
|
document.querySelector = origin
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('v-if + v-once', async () => {
|
||||||
|
const ok = ref(true)
|
||||||
|
const App = {
|
||||||
|
setup() {
|
||||||
|
return { ok }
|
||||||
|
},
|
||||||
|
template: `<div>{{ ok }}<div v-if="ok" v-once>{{ ok }}</div></div>`
|
||||||
|
}
|
||||||
|
const container = document.createElement('div')
|
||||||
|
createApp(App).mount(container)
|
||||||
|
|
||||||
|
expect(container.innerHTML).toBe(`<div>true<div>true</div></div>`)
|
||||||
|
ok.value = false
|
||||||
|
await nextTick()
|
||||||
|
expect(container.innerHTML).toBe(`<div>false<div>true</div></div>`)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('v-for + v-once', async () => {
|
||||||
|
const list = reactive([1])
|
||||||
|
const App = {
|
||||||
|
setup() {
|
||||||
|
return { list }
|
||||||
|
},
|
||||||
|
template: `<div>{{ list.length }}<div v-for="i in list" v-once>{{ i }}</div></div>`
|
||||||
|
}
|
||||||
|
const container = document.createElement('div')
|
||||||
|
createApp(App).mount(container)
|
||||||
|
|
||||||
|
expect(container.innerHTML).toBe(`<div>1<div>1</div></div>`)
|
||||||
|
list.push(2)
|
||||||
|
await nextTick()
|
||||||
|
expect(container.innerHTML).toBe(`<div>2<div>1</div></div>`)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
Loading…
x
Reference in New Issue
Block a user