Nuxt:将动态组件挂载到尚未渲染的 DOM

Nuxt: Mounting dynamic components to the DOM that is not rendered yet

场景:
我在 universal 模式下使用 Nuxt。该应用程序与无头 CMS 一起工作,该 CMS 提供应呈现的组件的简单布局,以及组件名称及其道具 - 如下所示:

[
  {
    "tag": "div",
    "class": "col",
    "component": "dogs",
    "props": {
      "dogs": [
        {
          "id": 1,
          "name": "Barky"
        },
        {
           "id": 2,
           "name": "Jumpy"
        }
      ]
     }
   },
   {
    "tag": "div",
    "class": "col",
    "component": "cats",
    "props": {
      "cats": [
        {
           "id": 1,
           "name": "Miouwy"
        },
        {
           "id": 2,
           "name": "Fluffy"
        }
      ]
    }
  }
]

据我了解,在 Nuxt 制作 "snapshot" 并将其交付给客户之前,我必须将组件应用到 DOM。我的计划是 安装 created() 生命周期中的组件——也就是说,只看名称,而不是要走的路。

主要问题:
我想将组件动态挂载到 DOM,它还不存在。


作为我想逃避的事情的一个例子——在 Nuxt 交付快照后安装组件——在 mounted() 生命周期中。

<template>
  <section class="container">
    <div ref="layout-container" class="row"></div>
  </section>
</template>

<script>
  import { mapGetters } from 'vuex';
  import Vue from 'vue';
  import Dogs from '@/components/Dogs';
  import Cats from '@/components/Cats';

  export default {
    components: {
      Dogs,
      Cats
    },
    fetch({ store }) {
      store.dispatch('landing/updateContent');
    },
    computed: {
      ...mapGetters({
        content: 'landing/content',
      })
    },
    beforeCreate() {
      Vue.component('dogs', Dogs);
      Vue.component('cats', Cats);
    },
    mounted() {
      this.content.forEach((item) => {
        const CompClass = Vue.component(item.component);
        const instance = new CompClass({ propsData: item.props }).$mount();
        this.$refs['layout-container'].appendChild(instance.$el);
      })
    }
  };
</script>

非常感谢您提前指导!

编辑: 回购这个例子:https://github.com/jpedryc/nuxt-test-render

尝试用 dynamic components

实现这个

模板:

<component :is="item.component" />

脚本:

components: { cats: Cats, dogs: Dogs },

那么您就不需要直接 DOM 操纵 hack。当 Nuxt 在服务器上 运行 时无法工作(因为服务器上没有真正的 DOM)并且还会阻止反应系统获取 pets 数组中的更改。

解决方案
我的主要问题是创建渲染布局并在 DOM 已交付给客户端后尝试将其连接起来。相反,我应该在虚拟 Vue DOM 中渲染组件 - 就在 "snapshot" 时刻之前。

这就是我最终所做的——不安装渲染组件:

<template>
  <section class="container">
    <page-component/> <!-- A component without <template>, but with render() -->
  </section>
</template>

PageComponent 仅包含:

import ...

export default {
  components: {
    Dogs,
    Cats,
  },
  beforeCreate() {
    Vue.component('dogs', Dogs);
    Vue.component('cats', Cats);
  },
  render: function (h) {
    return createDynamicLayout(h);
  },
}

createDynamicLayout(h) 只是一个创建树的简单函数:

return h('div', { 'class': 'row' }, [
  h('div', { 'class': 'col' }, h(<somwhere_call_dogs_component>)),
  h('div', { 'class': 'col' }, h(<somwhere_call_cats_component>)),
])