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
应该放什么?
此外,如果这些问题需要单独创建,请告诉我:
- dom 元素发生了什么变化?正如
console.log(this.$refs.provider);
清楚显示的那样,它不会被替换。
- 为什么每个人都反对手动安装组件?关于卸载代码的未决信息,在我看来,这种方式看起来比一堆 v-ifs 看起来更优雅。
(编辑:添加了第三个问题)
- 将 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-if
s 来控制必须渲染的组件。
我也很确定你不应该 $mount
在组件内部我认为这会导致一些副作用并且通常不是好的做法,因为至少有其他方法可以做到这一点.
关于混合 Vuetify 和 vanilla HTML,那里基本上没有问题。 Vuetify 的一些选择器非常具体(比如在带有 v-card 的 v-dialog 中使用 scrollable
)但大多数选择器更通用。
我有以下精简的代码,可以从下拉列表中动态安装组件:
<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
应该放什么?
此外,如果这些问题需要单独创建,请告诉我:
- dom 元素发生了什么变化?正如
console.log(this.$refs.provider);
清楚显示的那样,它不会被替换。 - 为什么每个人都反对手动安装组件?关于卸载代码的未决信息,在我看来,这种方式看起来比一堆 v-ifs 看起来更优雅。 (编辑:添加了第三个问题)
- 将 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-if
s 来控制必须渲染的组件。
我也很确定你不应该 $mount
在组件内部我认为这会导致一些副作用并且通常不是好的做法,因为至少有其他方法可以做到这一点.
关于混合 Vuetify 和 vanilla HTML,那里基本上没有问题。 Vuetify 的一些选择器非常具体(比如在带有 v-card 的 v-dialog 中使用 scrollable
)但大多数选择器更通用。