动态组件

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



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

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

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

<div id="app">
  <button @click="change">切换页面button>
  <component :is="currentTabComponent">component>
div>
Vue.component('home', {
	template: '
Home component
'
, }); Vue.component('posts', { template: '
Posts component
'
, }); Vue.component('archive', { template: '
Archive component
'
, }); 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: `
Home component
`
}, { template: `
Posts component
`
}, { template: `
Archive component
`
}, ], }, 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: `
Home component
`
}, { template: `
Posts component
`
}, { template: `
Archive component
`
}, ], }, 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>


<keep-alive :include="/a|b/">
  <component :is="view">component>
keep-alive>


<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: `
Home component
`
}, { template: `
Posts component
`
}, { template: `
Archive component
`
}, ], }, computed:{ currentTabComponent(){ return this.arr[this.index]; } }, methods:{ change(){ this.index = (++this.index) % this.arr.length; } } })
# 当组件在 内被切换,它的 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:`
Home component
`
, activated(){ this.$emit('pass-data','触发activated'); }, deactivated(){ this.$emit('pass-data','触发deactivated'); }, }, { template: `
Posts component
`
}, { template: `
Archive component
`
}, ], }, 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官方文档

你可能感兴趣的:(vue)