在 Vue.js 中动态挂载单个文件组件 [英] Dynamically mount a single file component in Vue.js
问题描述
我有一个文件组件 Main.Vue.
我还有另外三个单文件组件A.vue、B.vue和C.vue.
我希望每次都能在 Main.Vue 中显示不同的组件.我所做的是这样的:
<div><a v-if="isAVisible" ></a><b v-if="isBVisible" ></a>
</模板><脚本>从'./A.vue'导入A;从'./B.vue'导入B;...
这可行,但不完全是我想要的.我想要一个不同的文件 Factory.js,它负责导入所有组件 A、B、C,.. 并且具有返回我的组件的函数,我可以在 Main.vue 中以某种方式使用它.这是我尝试 Factory.js 的样子:
从'./A.vue'导入A;从'./B.vue'导入B;函数 getComponent(){如果 (..)返回新的 A();否则如果(..)返回新的 B();...}
这根本不起作用.我想要工厂文件方法,因为:
1) 我想把它拆分成不同的工厂文件
2) 我想将数据附加"到每个组件.所以我将有一个对象,其中包含返回实际组件的函数 + 一些附加数据,如名称"
任何想法如何做到这一点?
使用 Vue 的动态组件
您可以使用动态组件在组件之间动态切换.您需要将组件定义对象绑定到 component
元素的 is
属性 - Vue 的文档对此非常清楚.下面也是一个简单的例子:
<component :is="activeComponent"></component></模板>
从'component/a'导入componentA;从'component/b'导入componentB;导出默认{成分: {组分A,组分 B,},数据() {返回 {活动组件:'componentA',},},};
您可以直接将组件定义对象绑定到数据属性本身:
从'component/a'导入componentA;从'component/b'导入componentB;导出默认{数据() {返回 {活动组件:组件A,};},};
要切换组件,您可以通过编程方式更改 activeComponent
的值.
使用渲染函数
使用组件渲染函数可以实现更强大的动态挂载组件方式.为此,我们必须创建我们自己的版本 Vue 的component
元素——我们将其称为ElementProxy
:
从'component/a'导入componentA;从'component/b'导入componentB;导出默认{成分: {组分A,组分 B,},道具: {类型: {类型:字符串,要求:真实,},道具: {类型:对象,默认值:() =>({}),},},渲染(创建元素){const { props: attrs } = this;返回 createElement(element, { attrs });},};
您现在可以使用 ElementProxy
来代理元素.这样做的另一个好处是您可以将 props 作为对象传递,这将解决将 props 传递给具有不同模型的动态组件的问题.
<element-proxy :type="activeComponent" :props="props"></element-proxy></模板>
从'components/elementProxy'导入ElementProxy;导出默认{成分: {元素代理,},数据() {返回 {活动组件:'componentA',道具: { ... },};},};
进一步阅读
I have a single file component Main.Vue.
I also have three other single file components A.vue, B.vue and C.vue.
I want to be able to show inside Main.Vue a different component each time. What I did was this:
<template>
<div>
<a v-if="isAVisible" ></a>
<b v-if="isBVisible" ></a>
</div>
</template>
<script>
import A from './A.vue';
import B from './B.vue';
...
This works but not exactly what I wanted. I wanted a different file Factory.js, which does the importing of all the components A,B,C,.. And has functions that return my component, which I can use somehow in Main.vue. Here's what I tried Factory.js to look like:
import A from './A.vue';
import B from './B.vue';
function getComponent(){
if (..)
return new A();
else if (..)
return new B();
...
}
This didn't work at all. I want the factory file approach because:
1) I want to split it to different factory files
2) I want to "Attach" data to each component. So I'll have an object that contains the function returning the actual component + some additional data like "name"
Any ideas how to do this?
Use Vue's Dynamic Components
You could use Dynamic Components to dynamically switch between components. You will need to bind the component definition object to the is
attribute of the component
element – Vue's documentation on this is pretty self explanatory. Below is also a brief example:
<template>
<component :is="activeComponent"></component>
</template>
import componentA from 'component/a';
import componentB from 'component/b';
export default {
components: {
componentA,
componentB,
},
data() {
return {
activeComponent: 'componentA',
},
},
};
You could directly bind the component definition object to the data property itself:
import componentA from 'component/a';
import componentB from 'component/b';
export default {
data() {
return {
activeComponent: componentA,
};
},
};
To switch out components you can programmatically change the value of activeComponent
.
Use a render function
A more powerful way of dynamically mounting components can be achieved using component render functions. To do this we must create our own version of Vue's component
element – we'll call this the ElementProxy
:
import componentA from 'component/a';
import componentB from 'component/b';
export default {
components: {
componentA,
componentB,
},
props: {
type: {
type: String,
required: true,
},
props: {
type: Object,
default: () => ({}),
},
},
render(createElement) {
const { props: attrs } = this;
return createElement(element, { attrs });
},
};
You can now use the ElementProxy
to proxy elements. The additional benefit of this is that you can pass props in as an object which will solve the problem of passing props to dynamic components with differing models.
<template>
<element-proxy :type="activeComponent" :props="props"></element-proxy>
</template>
import ElementProxy from 'components/elementProxy';
export default {
components: {
ElementProxy,
},
data() {
return {
activeComponent: 'componentA',
props: { ... },
};
},
};
Further reading
- Vue's documentation for dynamic components
- Vue's documentation for the render function
- GitHub issue thread for binding props
这篇关于在 Vue.js 中动态挂载单个文件组件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!