简体   繁体   English

在 Vue.js 中动态挂载单个文件组件

[英]Dynamically mount a single file component in Vue.js

I have a single file component Main.Vue .我有一个文件组件Main.Vue

I also have three other single file components A.vue , B.vue and C.vue .我还有其他三个单文件组件A.vueB.vueC.vue

I want to be able to show inside Main.Vue a different component each time.我希望每次都能在 Main.Vue 中显示一个不同的组件。 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 .我想要一个不同的文件Factory.js ,它可以导入所有组件ABC ,.. 并且具有返回我的组件的函数,我可以在Main.vue中以某种方式使用它。 Here's what I tried Factory.js to look like:这是我尝试使用 Factory.js 的样子:

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 1)我想把它拆分成不同的工厂文件

2) I want to "Attach" data to each component. 2)我想将数据“附加”到每个组件。 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使用 Vue 的动态组件

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.您需要将组件定义对象绑定到component元素的is属性——Vue 的文档对此非常清楚。 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 .要切换组件,您可以通过编程方式更改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 :为此,我们必须创建我们自己版本的 Vue component元素——我们将其称为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.您现在可以使用ElementProxy来代理元素。 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进一步阅读

Yes, you need dynamic components:是的,您需要动态组件:

<template>
  <div>
    <component v-bind:is="currentView">
    <!-- component changes when vm.currentView changes! -->
    </component>
  </div>
</template>

<script>
import A from './A.vue';
import B from './B.vue';

export default {
  data: {
    currentView: 'A'
  },
  components: {
    A,
    B,
  }
})

then然后

function getComponent(){
  if (..)
    this.currentView = 'A';
  else if (..)
    this.currentView = 'B'
  ...
}

You can also bind components directly, according to manual:也可以直接绑定组件,按照手册:

https://v2.vuejs.org/v2/guide/components.html#Dynamic-Components https://v2.vuejs.org/v2/guide/components.html#Dynamic-Components

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM