最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Dynamically mount a single file component in Vue.js - Stack Overflow

programmeradmin0浏览0评论

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?

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?

Share Improve this question edited Feb 10, 2021 at 0:54 Kalnode 11.3k3 gold badges40 silver badges73 bronze badges asked May 5, 2017 at 7:53 Michael_S_Michael_S_ 5386 gold badges12 silver badges31 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 14

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

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

发布评论

评论列表(0)

  1. 暂无评论