动态组件

会有一股神秘感。 提交于 2020-01-02 16:19:08

有的时候,在不同的组件之间进行动态的切换时非常有用的,比如在一个多标签的界面里:
在这里插入图片描述
上述内容可以通过 Vue 的 <component> 元素加一个特殊的 is 特性来实现:

<!-- 组件会在 `currentTabComponent` 改变时改变 -->
<component v-bind:is="currentTabComponent"></component>

在上述示例中,currentTabComponent 可以包括:

  • 已注册组件的名字
  • 一个组件的选项对象

上示例: 首先是已注册组件的名字:

<div id="app">
  <button @click="change">切换页面</button>
  <component :is="currentTabComponent"></component>
</div>
Vue.component('home', {
	template: '<div>Home component</div>',
});
Vue.component('posts', {
	template: '<div>Posts component</div>',
});
Vue.component('archive', {
	template: '<div>Archive component</div>',
});
new Vue({
  el: '#app',
  components: {
    home,
    post,
    archive,
  },
  data:{
    index:0,
    arr:['home','post','archive'],
  },
  computed:{
    currentTabComponent(){
      return this.arr[this.index];
    }
  },
  methods:{
    change(){
      this.index = (++this.index) % 3;
    }
  }
});

上示例: 然后是直接绑定到组件对象上:

<div id="app">
  <button @click="change">切换页面</button>
  <component :is="currentTabComponent"></component>
</div>
new Vue({
  el: '#app',
  data:{
    index:0,
    arr:[
	  { template: `<div>Home component</div>` },
	  { template: `<div>Posts component</div>` },
	  { template: `<div>Archive component</div>` },
	],
  },
  computed:{
    currentTabComponent(){
      return this.arr[this.index];
    }
  },
  methods:{
    change(){
      this.index = (++this.index) % this.arr.length;
    }
  }
});

# 在动态组件上使用 keep-alive

当上述例子在组件之间切换的时候,你有时会想保持这些组件的状态,以避免反复重渲染导致的性能问题。

可以假设,上述例子中的 home 页面内容中存在一个 输入框, 当你在输入框中输入内容后,点击其余页面后,再点击home页面时,希望自己输入的内容仍然保留。使用 keep-alive 可以更轻松的帮你实现这个效果。

<!-- 失活的组件将会被缓存!-->
<div id="app">
  <button @click="change">切换页面</button>
  <keep-alive>
    <component :is="currentTabComponent"></component>  
  </keep-alive>
</div>
new Vue({
  el: '#app',
  data:{
    index:0,
    arr:[
	  { template: `<div>Home component</div>` },
	  { template: `<div>Posts component</div>` },
	  { template: `<div>Archive component</div>` },
	],
  },
  computed:{
    currentTabComponent(){
        return this.arr[this.index];
    }
  },
  methods:{
    change(){
      this.index = (++this.index) % this.arr.length;
    }
  }
})

注意这个 要求被切换到的组件都有自己的名字,不论是通过组件的 name 选项还是局部/全局注册。

  • Props: 给 keep-alive 组件传递参数
    • include - 字符串或正则表达式或数组。只有名称匹配的组件会被缓存。
    • exclude - 字符串或正则表达式或数组。任何名称匹配的组件都不会被缓存
    • max - 数字。最多可以缓存多少组件实例
<!-- 逗号分隔字符串 -->
<keep-alive include="a,b">
  <component :is="view"></component>
</keep-alive>

<!-- 正则表达式 (使用 `v-bind`) -->
<keep-alive :include="/a|b/">
  <component :is="view"></component>
</keep-alive>

<!-- 数组 (使用 `v-bind`) -->
<keep-alive :include="['a', 'b']">
  <component :is="view"></component>
</keep-alive>
# 当存在多个条件性的子元素, 要求同时只能存在一个元素被渲染:
<div id="app">
  <button @click="change">切换页面</button>
  <keep-alive>
    <home v-if="index === 0"></home>
    <posts v-else-if="index === 1"></posts>
    <archive v-else-if="index === 2"></archive>
  </keep-alive>
</div>
new Vue({
  el: '#app',
  data:{
    index:0,
    arr:[
	  { template: `<div>Home component</div>` },
	  { template: `<div>Posts component</div>` },
	  { template: `<div>Archive component</div>` },
	],
  },
  computed:{
    currentTabComponent(){
        return this.arr[this.index];
    }
  },
  methods:{
    change(){
      this.index = (++this.index) % this.arr.length;
    }
  }
})
# 当组件在 <keep-alive> 内被切换,它的 activateddeactivated 这两个生命周期钩子函数将会被对应执行:

在 2.2.0 及其更高版本中,activated 和 deactivated 将会在 树内的所有嵌套组件中触发。

<div id="app">
  <button @click="change">切换页面</button>
  <keep-alive>
    <component :is="currentTabComponent" @pass-data="getData"></component> 
  </keep-alive>
  <p>{{msg}}</p>
</div>
new Vue({
  el: '#app',
  data:{
    index:0,
    msg:'',    
    arr:[
      { 
        template:`<div>Home component</div>`,
        activated(){
          this.$emit('pass-data','触发activated');
        },
        deactivated(){
          this.$emit('pass-data','触发deactivated');
        },        
      },
	  { template: `<div>Posts component</div>` },
	  { template: `<div>Archive component</div>` },
    ],
  },
  computed:{
    currentTabComponent(){
        return this.arr[this.index];
    },
  },
  methods:{
    change(){
      this.index = (++this.index) % this.arr.length;
    },
    getData(value){
      this.msg = value;
      setTimeout(()=>{
        this.msg = '';
      },500)
    },
  },
})

参考资料

小火柴的蓝色理想
Vue官方文档

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!