Browse Source

fix(ssr): ensure v-text updates correctly with custom directives in SSR output (#12311)

close #12309
Bulat Aikaev 1 year ago
parent
commit
1f75d4e6df

+ 33 - 0
packages/compiler-ssr/__tests__/ssrElement.spec.ts

@@ -337,6 +337,39 @@ describe('ssr: element', () => {
         `)
     })
 
+    test('custom dir with v-text', () => {
+      expect(getCompiledString(`<div v-xxx v-text="foo" />`))
+        .toMatchInlineSnapshot(`
+          "\`<div\${
+              _ssrRenderAttrs(_ssrGetDirectiveProps(_ctx, _directive_xxx))
+            }>\${
+              _ssrInterpolate(_ctx.foo)
+            }</div>\`"
+        `)
+    })
+
+    test('custom dir with v-text and normal attrs', () => {
+      expect(getCompiledString(`<div class="test" v-xxx v-text="foo" />`))
+        .toMatchInlineSnapshot(`
+          "\`<div\${
+              _ssrRenderAttrs(_mergeProps({ class: "test" }, _ssrGetDirectiveProps(_ctx, _directive_xxx)))
+            }>\${
+              _ssrInterpolate(_ctx.foo)
+            }</div>\`"
+        `)
+    })
+
+    test('mulptiple custom dirs with v-text', () => {
+      expect(getCompiledString(`<div v-xxx v-yyy v-text="foo" />`))
+        .toMatchInlineSnapshot(`
+          "\`<div\${
+              _ssrRenderAttrs(_mergeProps(_ssrGetDirectiveProps(_ctx, _directive_xxx), _ssrGetDirectiveProps(_ctx, _directive_yyy)))
+            }>\${
+              _ssrInterpolate(_ctx.foo)
+            }</div>\`"
+        `)
+    })
+
     test('custom dir with object v-bind', () => {
       expect(getCompiledString(`<div v-bind="x" v-xxx />`))
         .toMatchInlineSnapshot(`

+ 23 - 18
packages/compiler-ssr/src/transforms/ssrTransformElement.ts

@@ -28,6 +28,7 @@ import {
   createSequenceExpression,
   createSimpleExpression,
   createTemplateLiteral,
+  findDir,
   hasDynamicKeyVBind,
   isStaticArgOf,
   isStaticExp,
@@ -164,24 +165,28 @@ export const ssrTransformElement: NodeTransform = (node, context) => {
             ]
           }
         } else if (directives.length && !node.children.length) {
-          const tempId = `_temp${context.temps++}`
-          propsExp.arguments = [
-            createAssignmentExpression(
-              createSimpleExpression(tempId, false),
-              mergedProps,
-            ),
-          ]
-          rawChildrenMap.set(
-            node,
-            createConditionalExpression(
-              createSimpleExpression(`"textContent" in ${tempId}`, false),
-              createCallExpression(context.helper(SSR_INTERPOLATE), [
-                createSimpleExpression(`${tempId}.textContent`, false),
-              ]),
-              createSimpleExpression(`${tempId}.innerHTML ?? ''`, false),
-              false,
-            ),
-          )
+          // v-text directive has higher priority than the merged props
+          const vText = findDir(node, 'text')
+          if (!vText) {
+            const tempId = `_temp${context.temps++}`
+            propsExp.arguments = [
+              createAssignmentExpression(
+                createSimpleExpression(tempId, false),
+                mergedProps,
+              ),
+            ]
+            rawChildrenMap.set(
+              node,
+              createConditionalExpression(
+                createSimpleExpression(`"textContent" in ${tempId}`, false),
+                createCallExpression(context.helper(SSR_INTERPOLATE), [
+                  createSimpleExpression(`${tempId}.textContent`, false),
+                ]),
+                createSimpleExpression(`${tempId}.innerHTML ?? ''`, false),
+                false,
+              ),
+            )
+          }
         }
 
         if (needTagForRuntime) {