Nuxt: Монтирование динамических компонентов в DOM, которые еще не отображаются - PullRequest
0 голосов
/ 12 октября 2018

Сценарий:
Я использую Nuxt в режиме universal.Приложение работает с автономной 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"
        }
      ]
    }
  }
]

Как я понимаю, я должен применять компонентыв DOM до того, как Nuxt сделает «снимок» и доставит его клиенту.Мой план состоял в том, чтобы смонтировать компонентов в жизненном цикле 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

Ответы [ 2 ]

0 голосов
/ 15 октября 2018

РЕШЕНИЕ
Моя основная проблема заключалась в создании визуализированного макета и попытке подключить его после того, как 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>)),
])
0 голосов
/ 13 октября 2018

Попробуйте реализовать это с динамическими компонентами

template:

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

script:

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

Тогда вам не нужнопрямая манипуляция с DOM.Это не может работать, когда Nuxt работает на сервере (потому что у вас нет реального DOM на сервере), а также не позволяет системе реагирования регистрировать изменения в массиве pets.

...