Nuxt:将动态组件安装到尚未渲染的DOM

时间:2018-10-12 10:41:27

标签: vue.js content-management-system vuex ssr nuxt

场景:
我在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制作“快照”并将其交付给客户端之前将组件应用于DOM。我的计划是在created()生命周期中安装组件-即,仅按名称查找,而不是查找方法。

主要问题:
我想将组件动态地安装到尚不存在的DOM。


mounted()生命周期中,作为我想避免的事情的一个示例(在Nuxt提供快照后安装组件)。

<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

2 个答案:

答案 0 :(得分:0)

尝试使用dynamic components

来实现

模板:

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

脚本:

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

那么您就不需要直接的DOM操作技巧。当Nuxt在服务器上运行时,这是行不通的(因为服务器上没有真正的DOM),并且还阻止了反应系统拾取pets数组中的更改。

答案 1 :(得分:0)

解决方案
我的主要问题是创建渲染的布局,并尝试在DOM已经交付给客户端之后将其挂接。相反,我应该在“快照”时刻之前在虚拟Vue DOM中渲染组件。

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

<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>)),
])