Просмотр исходного кода

fix(compiler-core): fix the detection of forwarded slots with v-if or v-for (#3353)

fix #3347
HcySunYang 5 лет назад
Родитель
Сommit
602b58ebd1

+ 18 - 3
packages/compiler-core/__tests__/transforms/vSlot.spec.ts

@@ -15,6 +15,7 @@ import { transformElement } from '../../src/transforms/transformElement'
 import { transformOn } from '../../src/transforms/vOn'
 import { transformBind } from '../../src/transforms/vBind'
 import { transformExpression } from '../../src/transforms/transformExpression'
+import { transformSlotOutlet } from '../../src/transforms/transformSlotOutlet'
 import {
   trackSlotScopes,
   trackVForSlotScopes
@@ -34,6 +35,7 @@ function parseWithSlots(template: string, options: CompilerOptions = {}) {
       ...(options.prefixIdentifiers
         ? [trackVForSlotScopes, transformExpression]
         : []),
+      transformSlotOutlet,
       transformElement,
       trackSlotScopes
     ],
@@ -737,9 +739,8 @@ describe('compiler: transform component slots', () => {
     expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()
   })
 
-  test('generate flag on forwarded slots', () => {
-    const { slots } = parseWithSlots(`<Comp><slot/></Comp>`)
-    expect(slots).toMatchObject({
+  describe('forwarded slots', () => {
+    const toMatch = {
       type: NodeTypes.JS_OBJECT_EXPRESSION,
       properties: [
         {
@@ -751,6 +752,20 @@ describe('compiler: transform component slots', () => {
           value: { content: `3 /* FORWARDED */` }
         }
       ]
+    }
+    test('<slot> tag only', () => {
+      const { slots } = parseWithSlots(`<Comp><slot/></Comp>`)
+      expect(slots).toMatchObject(toMatch)
+    })
+
+    test('<slot> tag w/ v-if', () => {
+      const { slots } = parseWithSlots(`<Comp><slot v-if="ok"/></Comp>`)
+      expect(slots).toMatchObject(toMatch)
+    })
+
+    test('<slot> tag w/ v-for', () => {
+      const { slots } = parseWithSlots(`<Comp><slot v-for="a in b"/></Comp>`)
+      expect(slots).toMatchObject(toMatch)
     })
   })
 

+ 19 - 8
packages/compiler-core/src/transforms/vSlot.ts

@@ -368,14 +368,25 @@ function buildDynamicSlot(
 function hasForwardedSlots(children: TemplateChildNode[]): boolean {
   for (let i = 0; i < children.length; i++) {
     const child = children[i]
-    if (child.type === NodeTypes.ELEMENT) {
-      if (
-        child.tagType === ElementTypes.SLOT ||
-        (child.tagType === ElementTypes.ELEMENT &&
-          hasForwardedSlots(child.children))
-      ) {
-        return true
-      }
+    switch (child.type) {
+      case NodeTypes.ELEMENT:
+        if (
+          child.tagType === ElementTypes.SLOT ||
+          (child.tagType === ElementTypes.ELEMENT &&
+            hasForwardedSlots(child.children))
+        ) {
+          return true
+        }
+        break
+      case NodeTypes.IF:
+        if (hasForwardedSlots(child.branches)) return true
+        break
+      case NodeTypes.IF_BRANCH:
+      case NodeTypes.FOR:
+        if (hasForwardedSlots(child.children)) return true
+        break
+      default:
+        break
     }
   }
   return false