--- /dev/null
+import { parse, transform, ElementNode, CallExpression } from '../../src'
+import { transformOnce } from '../../src/transforms/vOnce'
+import { transformElement } from '../../src/transforms/transformElement'
+import { createObjectMatcher } from '../testUtils'
+
+function transformWithCloak(template: string) {
+ const ast = parse(template)
+ transform(ast, {
+ nodeTransforms: [transformElement],
+ directiveTransforms: {
+ once: transformOnce
+ }
+ })
+ return ast.children[0] as ElementNode
+}
+
+describe('compiler: v-once transform', () => {
+ test('should add no props to DOM', () => {
+ const node = transformWithCloak(`<div v-once />`)
+ const codegenArgs = (node.codegenNode as CallExpression).arguments
+
+ // As v-cloak adds no properties the codegen should be identical to
+ // rendering a div with no props or reactive data (so just the tag as the arg)
+ expect(codegenArgs[1]).toMatchObject(
+ createObjectMatcher({
+ $once: `[true]`
+ })
+ )
+ })
+})
import { defaultOnError, createCompilerError, ErrorCodes } from './errors'
import { trackSlotScopes, trackVForSlotScopes } from './transforms/vSlot'
import { optimizeText } from './transforms/optimizeText'
+import { transformOnce } from './transforms/vOnce'
export type CompilerOptions = ParserOptions & TransformOptions & CodegenOptions
directiveTransforms: {
on: transformOn,
bind: transformBind,
+ once: transformOnce,
...(options.directiveTransforms || {}) // user transforms
}
})
--- /dev/null
+import {
+ DirectiveTransform,
+ createObjectProperty,
+ createSimpleExpression
+} from '@vue/compiler-core'
+
+export const transformOnce: DirectiveTransform = dir => {
+ return {
+ props: createObjectProperty(
+ createSimpleExpression(`$once`, true, dir.loc),
+ createSimpleExpression('true', false)
+ ),
+ needRuntime: false
+ }
+}
}
export const isSimpleIdentifier = (name: string): boolean =>
- !/^\d|[^\w]/.test(name)
+ !/^\d|[^\$\w]/.test(name)
export function getInnerRange(
loc: SourceLocation,
import {
parse,
transform,
- CompilerOptions,
- ElementNode
+ ElementNode,
+ CallExpression
} from '@vue/compiler-core'
import { transformCloak } from '../../src/transforms/vCloak'
import { transformElement } from '../../../compiler-core/src/transforms/transformElement'
-import { CallExpression } from '../../src'
-function transformWithCloak(template: string, options: CompilerOptions = {}) {
+function transformWithCloak(template: string) {
const ast = parse(template)
transform(ast, {
nodeTransforms: [transformElement],
directiveTransforms: {
cloak: transformCloak
- },
- ...options
+ }
})
return ast.children[0] as ElementNode
}
-describe('compiler: `v-cloak` transform', () => {
+describe('compiler: v-cloak transform', () => {
test('should add no props to DOM', () => {
const node = transformWithCloak(`<div v-cloak/>`)
const codegenArgs = (node.codegenNode as CallExpression).arguments
optimized: boolean = false
) {
// patching & not same type, unmount old tree
- if (n1 != null && !isSameType(n1, n2)) {
- anchor = getNextHostNode(n1)
- unmount(n1, parentComponent, parentSuspense, true)
- n1 = null
+ if (n1 != null) {
+ if (!isSameType(n1, n2)) {
+ anchor = getNextHostNode(n1)
+ unmount(n1, parentComponent, parentSuspense, true)
+ n1 = null
+ } else if (n1.props && n1.props.$once) {
+ console.log(111)
+ return
+ }
}
const { type, shapeFlag } = n2
const vnodeHooksRE = /^vnode/
export const isReservedProp = (key: string): boolean =>
- key === 'key' || key === 'ref' || vnodeHooksRE.test(key)
+ key === 'key' || key === 'ref' || key === '$once' || vnodeHooksRE.test(key)
const camelizeRE = /-(\w)/g
export const camelize = (str: string): string => {