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

Posted

技术标签:

【中文标题】Nuxt:将动态组件挂载到尚未渲染的 DOM【英文标题】:Nuxt: Mounting dynamic components to the DOM that is not rendered yet 【发布时间】:2019-03-17 13:59:53 【问题描述】:

场景: 我在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。


作为我想逃避的事情的一个例子 - 在 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

【问题讨论】:

【参考方案1】:

尝试使用dynamic components 实现此功能

模板:

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

脚本:

components:  cats: Cats, dogs: Dogs ,

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

【讨论】:

感谢您的帮助。这个解决方案在定义的布局中会很好,但是上面的 items 数组是定义多个组件的多级对象数组(带有“子”键)的简化。我认为解决此问题的最佳方法是在将 DOM 提供给客户端之前尝试在服务器端渲染 DOM。【参考方案2】:

解决方案 我的主要问题是创建渲染布局并在 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>)),
])

【讨论】:

以上是关于Nuxt:将动态组件挂载到尚未渲染的 DOM的主要内容,如果未能解决你的问题,请参考以下文章

15《Vue 入门教程》Vue 动态组件 &amp;amp; keep-alive

react-router-dom 开关在动态路径后不渲染组件

Vue 开发实战生态篇 # 22:Nuxt核心原理是什么?

vue的优化

vue的优化

在动态组件中访问 nuxt $store