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
实现这个
模板:
<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>)),
])
场景:
我在 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
模板:
<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>)),
])