]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix: add anchors for template v-if node in vnode-based slot
authordaiwei <daiwei521@126.com>
Tue, 12 Aug 2025 09:46:52 +0000 (17:46 +0800)
committerdaiwei <daiwei521@126.com>
Tue, 12 Aug 2025 09:46:52 +0000 (17:46 +0800)
packages/compiler-core/src/ast.ts
packages/compiler-ssr/__tests__/ssrVaporAnchors.spec.ts
packages/compiler-ssr/src/transforms/ssrTransformComponent.ts

index dfcc1bef3c35d0f07ed9a4048d7abe61367878ad..1ecab369a32e1c3b98ccca4322291be77901257c 100644 (file)
@@ -180,6 +180,7 @@ export interface TemplateNode extends BaseElementNode {
   tagType: ElementTypes.TEMPLATE
   // TemplateNode is a container type that always gets compiled away
   codegenNode: undefined
+  anchor?: string
 }
 
 export interface TextNode extends Node {
index f5747b5b325dd3f3792be3a5ea6f42dd50cb3172..a2aab28e749dad855ad08a548abb631243d5db35 100644 (file)
@@ -351,6 +351,60 @@ describe('insertion anchors', () => {
       `)
     })
 
+    test('prepend anchor with template v-if', () => {
+      expect(
+        getCompiledString(
+          `<component :is="tag">
+            <div v-if="foo">
+              <template v-if="depth < 5">
+                foo
+              </template>
+              <div></div>
+            </div>
+          </component>`,
+          { vapor: true },
+        ),
+      ).toMatchInlineSnapshot(`
+        "\`<!--[a-->\`)
+          _ssrRenderVNode(_push, _createVNode(_resolveDynamicComponent(_ctx.tag), null, {
+            default: _withCtx((_, _push, _parent, _scopeId) => {
+              if (_push) {
+                if (_ctx.foo) {
+                  _push(\`<div\${_scopeId}><!--[p-->\`)
+                  if (_ctx.depth < 5) {
+                    _push(\`<!--[--> foo <!--]-->\`)
+                    _push(\`<!--if-->\`)
+                  } else {
+                    _push(\`<!---->\`)
+                  }
+                  _push(\`<!--p]--><div\${_scopeId}></div></div>\`)
+                  _push(\`<!--if-->\`)
+                } else {
+                  _push(\`<!---->\`)
+                }
+              } else {
+                return [
+                  (_ctx.foo)
+                    ? (_openBlock(), _createBlock("div", { key: 0 }, [
+                        _createCommentVNode("[p"),
+                        (_ctx.depth < 5)
+                          ? (_openBlock(), _createBlock(_Fragment, { key: 0 }, [
+                              _createTextVNode(" foo ")
+                            ], 64 /* STABLE_FRAGMENT */))
+                          : _createCommentVNode("v-if", true),
+                        _createCommentVNode("p]"),
+                        _createVNode("div")
+                      ]))
+                    : _createCommentVNode("v-if", true)
+                ]
+              }
+            }),
+            _: 1 /* STABLE */
+          }), _parent)
+          _push(\`<!--dynamic-component--><!--a]-->\`"
+      `)
+    })
+
     test('prepend anchor with v-for', () => {
       expect(
         getCompiledString('<div><span v-for="item in items"/><span/></div>', {
index 5137da0e28667a5ee163f7122f9ef548aedde7dc..beec63151c851966e6d02b166e650e4147e25386 100644 (file)
@@ -417,7 +417,11 @@ function injectVaporInsertionAnchors(
     const { tagType, props } = child
     let anchor: string | undefined
 
-    if (tagType === ElementTypes.COMPONENT || tagType === ElementTypes.SLOT) {
+    if (
+      tagType === ElementTypes.COMPONENT ||
+      tagType === ElementTypes.SLOT ||
+      tagType === ElementTypes.TEMPLATE
+    ) {
       anchor = child.anchor
     } else if (tagType === ElementTypes.ELEMENT) {
       let hasIf = false