vue手动挂载和卸载组件

Vue manually mounting & remounting components

我有以下精简的代码,可以从下拉列表中动态安装组件:

<template>
  <v-app>
    <v-container>
      <v-layout>
        <v-select label="Providers"
          single-line
          :items="providers"
          item-text="txt"
          item-value="val"
          :v-model="provider"
          v-on:change="setProvider" />
        
        <div ref='provider' id='provider' />
      </v-layout>
    </v-container>
  </v-app>
</template>

<script>

import Provider1 from './components/Provider'
import Provider2 from './components/Provider2'
import Vue from 'vue'
import vuetify from './plugins/vuetify';

export default {
  data: () => {
    return {
      provider: null,
      providers: [
        {txt: 'a', val: Provider1},
        {txt: 'b', val: Provider2}
      ],
    };
  },

  methods: {
    setProvider(val) {
      console.log(this.$refs.provider);

      if (this.provider) {
        // unmount and/or re-create #provider dom element
      }

      this.provider = new (Vue.extend(val))({
        vuetify,
      }).$mount('#provider');
    }
  },
}

</script>

第一次选择效果很好,随后的选择使我的控制台 window 使用“[Vue warn]: Cannot find element: #provider// unmount and/or re-create #provider dom element应该放什么?

此外,如果这些问题需要单独创建,请告诉我:

  1. dom 元素发生了什么变化?正如 console.log(this.$refs.provider); 清楚显示的那样,它不会被替换。
  2. 为什么每个人都反对手动安装组件?关于卸载代码的未决信息,在我看来,这种方式看起来比一堆 v-ifs 看起来更优雅。 (编辑:添加了第三个问题)
  3. 将 vanilla 标记与 Vuetify 混合使用是否有任何缺点,例如上述 <div />

谢谢

(编辑:修改后的工作代码。我添加了一个 emit 以获得额外的乐趣)

<template>
  <v-app>
    <v-app-bar app />
    <v-main>
        <v-select label="Providers"
          :items="providers"
          v-model="provider" />
      <component :is="provider" @fb="feedback" />
    </v-main>
  </v-app>
</template>

<script>

import Provider1 from './components/Provider'
import Provider2 from './components/Provider2'

export default {
  data: () => {
    return {
      provider: null,
      providers: [
        {text: 'a', value: Provider1},
        {text: 'b', value: Provider2}
      ],
    };
  },

  methods: {
    feedback(v) {
      alert(v);
    }
  }
}

</script>

如果您的 objective 是在动态组件之间切换,您可以使用 is Vue keyword 构建动态组件。这样你就不需要使用 v-ifs 来控制必须渲染的组件。

我也很确定你不应该 $mount 在组件内部我认为这会导致一些副作用并且通常不是好的做法,因为至少有其他方法可以做到这一点.

关于混合 Vuetify 和 vanilla HTML,那里基本上没有问题。 Vuetify 的一些选择器非常具体(比如在带有 v-card 的 v-dialog 中使用 scrollable)但大多数选择器更通用。