Subscribe on changes!

v-text and v-html and may be other built-in (custom may be too) directives on custom component with slot in SSR

avatar
Aug 9th 2022

Vue version

3

Link to minimal reproduction

Vue 3 https://stackblitz.com/edit/github-lf1exv?terminal=dev

Nuxt 3 https://github.com/max5432112345/nuxt-error-2/

Steps to reproduce

If use v-text on custom component with slot when in SPA text is displayed in page but in SSR not displayed (hot reload only sometime make it to display but after refresh page disappear).

Index.vue

<template>
  <div>
    <CustomText v-text="'test'" />
     <CustomText> TEST </CustomText>
  </div>
</template>

CustomText.vue

<template>
  <span>
    <slot name="default" />
  </span>
</template>

What is expected?

We certainly want behaviour similar on SSR vs SPA when using v-text

What is actually happening?

In vue 2 it produced early warnings (Hydration children mismatch) when used v-text without inner text (and I add $nbsp; to bypass that) but now no errors or warnings. Now in vue 3 it not permit to use inner text and v-text together.

In that situation it not show errors or warnings like vue 2:

System Info

vue 3
linux

Any additional comments?

https://github.com/nuxt/nuxt.js/issues/14530

avatar
Aug 11th 2022

@yyx990803 v-html the same story.

avatar
Nov 15th 2022

@yyx990803

avatar
Nov 29th 2022

The root cause is that directives with children overwrite (e.g. v-html & v-text) are not working with Component yet in SSR. here is a workaround

avatar
Feb 5th 2023

@edison1105 Can we get any ETA for this issue?

avatar
Feb 13th 2023

+ 1

avatar
Mar 15th 2023
  • This problem is still present
avatar
Jul 18th 2023

My use case:

I want to create a JSON-LD script tag with metadata. I want to use data passed to a component as props.

No workaround is available for this AFAIK.

avatar
Sep 15th 2023

Here is my workaround:

/**
 * This is similar to `component(:is="tag")`, except that it also works in SSR.
 *
 * See:
 * - https://discord.com/channels/473401852243869706/1152225826910244955/1152225826910244955
 * - https://stackblitz.com/edit/github-gs1ptn
 * - https://github.com/vuejs/core/issues/6553#issuecomment-1232468857
 * - https://github.com/vuejs/core/issues/6435
 * - https://play.vuejs.org/#__SSR__eNp9UctOwzAQ/BXLl7RSlR64hbQSVJUA8RL0hjlEybZ1SWzLXpdIVf4dP5ISJMCHaDM7O57xnuiVUunRAs1ojtCoukBYMkFIXvFjKFy5sgZls4EWSYbuu2A0QTCYMErmkT2P9Hw+EslNqblCYgCtcv+8UVIjGalttWxIks5XsgkuEq8Qp5Z0RgfYm+vRs8qJ7EnXC8RJaEOjgm1ha0fwvpSWymRvzm2LyfvMQ8HNJDSmkUSIdpgWZDIliz4zIftJ4jIls4HjDxcC9M3m4T6LyqnXDar+dNNLX3YO6H4GQVNKseW79GCkcGmCJKOly8dr0E8KuRSG0Wy4jNGiruXnXcBQW+gvcTN7KD9+wQ+m9RijzxoM6CMweu5hoXeAsb1+fXSeR81GVrZ27H+aL2Bkbb3HSLu2onK2R7zg9jZshovdxqxbBGGGUN7o8DKe7fblV/tX9G+7F+lFmHMPSrsvfIzfCg==
 */
export default defineComponent({
  props: {
    tag: {
      type: String,
      required: true,
    },
    html: {
      type: String,
      required: true,
    },
  },

  setup(props, { slots }) {
    return () => h(props.tag, { innerHTML: props.html });
  },
});
avatar
Dec 6th 2023

Not that hard to make your own v-html directive that works SSR. Here is mine:

  nuxtApp.vueApp.directive('thtml', {
    mounted: (el: HTMLElement, binding: any, vnode: any) => {
      el.innerHTML = binding.value;
    },
    getSSRProps(binding: any) {
      return {
        innerHTML: binding.value
      }
    }
  })