daiwei hace 1 año
padre
commit
81992b0f8e

+ 1 - 0
packages/compiler-core/src/ast.ts

@@ -144,6 +144,7 @@ export interface PlainElementNode extends BaseElementNode {
     | SimpleExpressionNode // when hoisted
     | CacheExpression // when cached by v-once
     | MemoExpression // when cached by v-memo
+    | ConditionalExpression
     | undefined
   ssrCodegenNode?: TemplateLiteral
 }

+ 2 - 0
packages/compiler-core/src/compile.ts

@@ -22,6 +22,7 @@ import { transformModel } from './transforms/vModel'
 import { transformFilter } from './compat/transformFilter'
 import { ErrorCodes, createCompilerError, defaultOnError } from './errors'
 import { transformMemo } from './transforms/vMemo'
+import { transformSkip } from './transforms/vSkip'
 
 export type TransformPreset = [
   NodeTransform[],
@@ -35,6 +36,7 @@ export function getBaseTransformPreset(
     [
       transformOnce,
       transformIf,
+      transformSkip,
       transformMemo,
       transformFor,
       ...(__COMPAT__ ? [transformFilter] : []),

+ 4 - 0
packages/compiler-core/src/errors.ts

@@ -90,6 +90,8 @@ export enum ErrorCodes {
   X_V_MODEL_ON_PROPS,
   X_INVALID_EXPRESSION,
   X_KEEP_ALIVE_INVALID_CHILDREN,
+  X_V_SKIP_NO_EXPRESSION,
+  X_V_SKIP_ON_TEMPLATE,
 
   // generic errors
   X_PREFIX_ID_NOT_SUPPORTED,
@@ -179,6 +181,8 @@ export const errorMessages: Record<ErrorCodes, string> = {
   [ErrorCodes.X_INVALID_EXPRESSION]: `Error parsing JavaScript expression: `,
   [ErrorCodes.X_KEEP_ALIVE_INVALID_CHILDREN]: `<KeepAlive> expects exactly one child component.`,
   [ErrorCodes.X_VNODE_HOOKS]: `@vnode-* hooks in templates are no longer supported. Use the vue: prefix instead. For example, @vnode-mounted should be changed to @vue:mounted. @vnode-* hooks support has been removed in 3.4.`,
+  [ErrorCodes.X_V_SKIP_NO_EXPRESSION]: `v-skip is missing expression.`,
+  [ErrorCodes.X_V_SKIP_ON_TEMPLATE]: `v-skip cannot be used on <template> or <slot> tags.`,
 
   // generic errors
   [ErrorCodes.X_PREFIX_ID_NOT_SUPPORTED]: `"prefixIdentifiers" option is not supported in this build of compiler.`,

+ 1 - 1
packages/compiler-core/src/transforms/vIf.ts

@@ -217,7 +217,7 @@ function createIfBranch(node: ElementNode, dir: DirectiveNode): IfBranchNode {
   }
 }
 
-function createCodegenNodeForBranch(
+export function createCodegenNodeForBranch(
   branch: IfBranchNode,
   keyIndex: number,
   context: TransformContext,

+ 70 - 0
packages/compiler-core/src/transforms/vSkip.ts

@@ -0,0 +1,70 @@
+import {
+  type IfBranchNode,
+  NodeTypes,
+  type SimpleExpressionNode,
+  createConditionalExpression,
+  createSimpleExpression,
+} from '../ast'
+import {
+  type NodeTransform,
+  createStructuralDirectiveTransform,
+} from '../transform'
+import {
+  ErrorCodes,
+  createCompilerError,
+  findProp,
+  isSlotOutlet,
+  isTemplateNode,
+  processExpression,
+} from '@vue/compiler-core'
+import { createCodegenNodeForBranch } from './vIf'
+import { validateBrowserExpression } from '../validateExpression'
+
+export const transformSkip: NodeTransform = createStructuralDirectiveTransform(
+  'skip',
+  (node, dir, context) => {
+    if (isTemplateNode(node) || isSlotOutlet(node)) {
+      const loc = dir.exp ? dir.exp.loc : node.loc
+      context.onError(createCompilerError(ErrorCodes.X_V_SKIP_ON_TEMPLATE, loc))
+      return
+    }
+
+    if (!dir.exp || !(dir.exp as SimpleExpressionNode).content.trim()) {
+      const loc = dir.exp ? dir.exp.loc : node.loc
+      context.onError(
+        createCompilerError(ErrorCodes.X_V_SKIP_NO_EXPRESSION, dir.loc),
+      )
+      dir.exp = createSimpleExpression(`true`, false, loc)
+    }
+
+    if (!__BROWSER__ && context.prefixIdentifiers && dir.exp) {
+      dir.exp = processExpression(dir.exp as SimpleExpressionNode, context)
+    }
+
+    if (__DEV__ && __BROWSER__ && dir.exp) {
+      validateBrowserExpression(dir.exp as SimpleExpressionNode, context)
+    }
+
+    return () => {
+      const consequent: IfBranchNode = {
+        type: NodeTypes.IF_BRANCH,
+        loc: node.loc,
+        condition: undefined,
+        children: node.children,
+        userKey: findProp(node, `key`),
+      }
+      const alternate: IfBranchNode = {
+        type: NodeTypes.IF_BRANCH,
+        loc: node.loc,
+        condition: undefined,
+        children: [node],
+        userKey: findProp(node, `key`),
+      }
+      node.codegenNode = createConditionalExpression(
+        dir.exp!,
+        createCodegenNodeForBranch(consequent, 0, context),
+        createCodegenNodeForBranch(alternate, 1, context),
+      )
+    }
+  },
+)

+ 1 - 1
packages/shared/src/general.ts

@@ -90,7 +90,7 @@ export const isReservedProp: (key: string) => boolean = /*@__PURE__*/ makeMap(
 
 export const isBuiltInDirective: (key: string) => boolean =
   /*@__PURE__*/ makeMap(
-    'bind,cloak,else-if,else,for,html,if,model,on,once,pre,show,slot,text,memo',
+    'bind,cloak,else-if,else,for,html,if,model,on,once,pre,show,slot,text,memo,skip',
   )
 
 const cacheStringFunction = <T extends (str: string) => string>(fn: T): T => {