Search code examples
vue.jsdomrendernuxt.js

Nuxt render function for a string of HTML that contains Vue components


I'm trying to solve this for Nuxt

Codesandbox of a WIP not working: https://codesandbox.io/s/zw26v3940m

OK, so I have WordPress as a CMS, and it's outputting a bunch of HTML. A sample of the HTML looks like this:

'<h2>A heading tag</h2>
<site-banner image="{}" id="123">Slot text here</site-banner>
<p>some text</p>'

Notice that it contains a Vue component <site-banner> that has some props on it (the image prop is a JSON object I left out for brevity). That component is registered globally.

I have a component that we wrote, called <wp-content> that works great in Vue, but doesn't work in Nuxt. Note the two render functions, one is for Vue the other is for Nuxt (obviously this is for examples sake, I wouldn't use both).

export default {
    props: {
        html: {
            type: String,
            default: ""
        }
    },
    render(h, context) {
        // Worked great in Vue
        return h({ template: this.html })
    }      
    render(createElement, context) {
        // Kind of works in Nuxt, but doesn't render Vue components at all
        return createElement("div", { domProps: { innerHTML: this.html } })
    } 
}

So the last render function works in Nuxt except it won't actually render the Vue components in this.html, it just puts them on the page as HTML.

So how do I do this in Nuxt? I want to take a string of HTML from the server, and render it on the page, and turn any registered Vue components into proper full-blown Vue components. Basically a little "VueifyThis(html)" factory.


Solution

  • This was what worked and was the cleanest, thanks to Jonas Galvez from the Nuxt team via oTechie.

    export default {
      props: {
        html: {
          type: String,
          default: ""
        }
      },
      render(h) {
        return h({
          template: `<div>${this.html}</div>`
        });
      }
    };
    

    Then in your nuxt.config.js file:

        build: {
            extend(config, ctx) {
                // Include the compiler version of Vue so that <component-name> works
                config.resolve.alias["vue$"] = "vue/dist/vue.esm.js"
            }
        }