vue 动态组件切换的几种实现方式

9,023 阅读6分钟

vue 动态组件

使用场景 如tab页面切换的功能。可以直接使用vue的component,也可以使用v-if来实现。具体如下:

方法一

<div id="example">
    <button @click="change">切换页面</button>
    <keep-alive>
        <component :is="currentView"></component>
    </keep-alive>
</div>

is可绑定的值可以是组件名称,也是是一个组件对象。通过动态切换绑定的值,就可以实现tab页式的效果。

下例是组件名称的方式:

new Vue({
               el"#example",
               data:{
                   index0,
                   attrs:["page1","page2","page3"]
               }
               ,components: {
                   page1:{template:`<div>组件页1</div>`},
                   page2:{template:`<div>组件页2</div>`},
                   page3:{template:`<div>组件页3</div>`},
               },methods:{
                   change:function ({
                       const len = this.attrs.length
                       this.index = (++this.index)%len
                   }
               },computed:{
                   currentView:function ({
                       return this.attrs[this.index]
                   }
               }
           })

下例是组件对象的方式:

new Vue({
                el"#example",
                data:{
                    index0,
                    attrs:[
                        {template:`<div>组件页1</div>`}
                        ,{template:`<div>组件页2</div>`}
                        ,{template:`<div>组件页3</div>`}
                    ]
                }
               ,methods:{
                    change:function ({
                        const len = this.attrs.length
                        this.index = (++this.index)%len
                    }
                },computed:{
                    currentView:function ({
                        return this.attrs[this.index]
                    }
                }
            })

方法二 使用v-if,v-else-if,v-else来控制显示具体的哪一个组件。

<div id="example_demo">
           <button @click="change">切换页面</button>
           <keep-alive>
               <home v-if="index===0"></home>
               <posts v-else-if="index===1"></posts>
               <archive v-else></archive>
           </keep-alive>
       </div>
 new Vue({
    el"#example_demo",
    data:{
        index0,
    }
    ,components: {
        home:{template:`<div>我是主页</div>`},
        posts:{template:`<div>我是提交页</div>`},
        archive:{template:`<div>我是存档页</div>`},
    },methods:{
        change:function ({
            let len = Object.keys(this.$options.components).length
            this.index = (++this.index)%len
        }
    }
})

组件激活事件 当组件在  内被切换,它的 activated 和 deactivated 这两个生命周期钩子函数将会被对应执行。

  
{
    template:`<div>组件页1</div>`,
    activated(){
        this.$emit('pass-data'"组件被添加")
    },
    deactivated(){
        this.$emit('pass-data'"组件被移除")
    }
}

可用如上所示代码添加添加这2个生命期钩子函数,然后通过自定义事件的方式,向外发送事件通知。

  组件有条件地缓存【include和exclude】
+include - 字符串或正则表达式。只有名称匹配的组件会被缓存。
-exclude - 字符串或正则表达式。任何名称匹配的组件都不会被缓存。
max - 数字。最多可以缓存多少组件实例。
匹配首先检查组件自身的 name 选项,如果 name 选项不可用,则匹配它的局部注册名称(父组件 components 选项的键值)。匿名组件不能被匹配

具体示例如下:

  <!-- 逗号分隔字符串 -->
<keep-alive include="a,b">
  <component :is="view"></component>
</keep-alive>
<!-- 正则表达式 (使用 v-bind) -->
<keep-alive :include="/a|b/">
  <component :is="view"></component>
</keep-alive>
<!-- Array (use v-bind) -->
<keep-alive :include="['a', 'b']">
  <component :is="view"></component>
</keep-alive>

vue 利用component组件和is属性实现动态组件

vue 新的布局方式,通过config配置,利用component组件和is属性来控制页面里面展示内容,在这里简单做一个 dome

1,首先新建一些组件的vue页面

这个文件的目录,其中component中的是页面展示的组件

  src
   assets  // 静态文件
   component  // 组件文件
        BaseInfo.vue
        OpenInfo.vue
        CommentReview.vue
        OrderInfo.vue
    config  // 配置文件
        index.js
    view  // 页面内容
        index.vue

这里展示一下 每一个组件中的内容-只是背景颜色不同-其他的就不一一展示


<template>
<div class="EquipmentFailure">
  <div class="content">我是 BaseInfo 页面 11111111111111111111111111111111111</div>
</div>
</template>
<script>
export default {
name'EquipmentFailure',
components: {},
data () {
  return {
  }
},
created () {},
methods: {}
}
</script>
<style lang="scss" scoped>
.content {
display: flex;
justify-content: space-between;
width1000px;
height200px;
background-color: red;
}
</style>

2.config 文件中的配置

const open = function ({
const vm = this
return [
  {
  // type:‘’  可以通过type类型来判断展示那些组件内容
    modules: [
      {
        id'baseInfo',
        refName'baseInfo',
        type'baseInfo',
        component() => import('@/components/open/BaseInfo')
      },
      {
        id'lineInfo',
        refName'lineInfo',
        type'lineInfo',
        component() => import('@/components/OpenInfo')
      },
      {
        id'reviewInfo',
        refName'reviewInfo',
        type'reviewInfo',
        component() => import('@/components/CommentReview')
      },
      {
        id'orderInfo',
        refName'orderInfo',
        type'orderInfo',
        component() => import('@/components/OrderInfo')
      }
    ]
  }
]
}

export const openModules = vm => {
return open.call(vm)
}

3,展示页面中的操作

<template>
<div class="content">
  <div>我是 index</div>
  <el-button @click="Handover">切换</el-button>
  <div v-for="(content,index) in openListValue" :key="index">
    <!-- component标签创建动态组件,is属性指向谁,就显示哪个组件 -->

    <component
      :is="content.type==`${componentName}`?content.component:''"
      :key="content.index"
      :ref="content.refName"
      :type="content.type"
      :ref-name="content.refName"
    >
</component>
  </div>
</div>
</template>
<script>
import { openModules } from './config'

export default {
data () {
  return {
    componentName'baseInfo',
    index0,
    openList: [],
    openListValue: []
  }
},
mounted () {
  this.getList()
},
methods: {
  Handover () {
    this.index++
    switch (this.index) {
      case 0:
        this.componentName = 'baseInfo'
        break
      case 1:
        this.componentName = 'lineInfo'
        break
      case 2:
        this.componentName = 'reviewInfo'
        break
      case 3:
        this.componentName = 'orderInfo'
        break

      default:
        break
    }
    if (this.index == 4) {
      this.index = 0
      this.componentName = 'baseInfo'
    }
  },
  getList () {
    this.openList = openModules(this)[0]
    console.log(this.openList)
    this.openListValue = this.openList.modules
  }
}
}
</script>
<style scoped>
.content {
padding-top20px;
display: flex;
flex-direction: column;
width1000px;
}
</style>

页面展示

本文使用 mdnice 排版