跳至主要內容

动态组件

大约 3 分钟

切换组件案例

  • 比如我们现在想要实现了一个功能:

    • 点击一个tab-bar,切换不同的组件显示;
  • 这个案例我们可以通过两种不同的实现思路来实现:

    • 方式一:通过v-if来判断,显示不同的组件;
    • 方式二:动态组件的方式;

v-if显示不同的组件

<template>
  <div>
    <button v-for="item in tabs" :key="item" @click="itemClick(item)" :class="{ active: currentTab === item }">
      {{ item }}
    </button>

    <!-- 1.v-if的判断实现 -->
    <template v-if="currentTab === 'home'">
      <home></home>
    </template>
    <template v-else-if="currentTab === 'about'">
      <about></about>
    </template>
    <template v-else>
      <category></category>
    </template>
  </div>
</template>

动态组件

Vue.js 的动态组件是指可以根据不同的数据渲染不同的组件的功能。你可以使用 Vue.js 的 <component> 元素来实现动态组件。

例如,你可以在父组件中定义一个数据属性,根据这个属性的值来决定渲染哪个子组件。然后,在模板中使用 <component> 元素,并将该数据属性绑定到 is 属性上,这样就可以动态地渲染不同的子组件了。

<script>
import Home from './Home.vue'
import Posts from './Posts.vue'
import Archive from './Archive.vue'
  
export default {
  components: {
    Home,
    Posts,
    Archive
  },
  data() {
    return {
      currentTab: 'Home',
      tabs: ['Home', 'Posts', 'Archive']
    }
  }
}
</script>

<template>
  <div class="demo">
    <button
       v-for="tab in tabs"
       :key="tab"
       :class="['tab-button', { active: currentTab === tab }]"
       @click="currentTab = tab"
     >
      {{ tab }}
    </button>
	  <component :is="currentTab" class="tab"></component>
  </div>
</template>

动态组件的传值

<component :is="currentTab"
            name="coderwhy"
            :age="18"
            @pageClick="pageClick">
</component>
pageClick() {
  console.log("page内部发生了点击");
}
export default {
  name: "home",  
  props: {
    name: {
      type: String,
      default: ""
    },
    age: {
      type: Number,
      default: 0
    }
  }
}

keep-alive

https://cn.vuejs.org/guide/built-ins/keep-alive.html#keepalive

<KeepAlive> 是一个内置组件,它的功能是在多个组件间动态切换时缓存被移除的组件实例。

默认情况下,一个组件实例在被替换掉后会被销毁。这会导致它丢失其中所有已变化的状态——当这个组件再一次被显示时,会创建一个只带有初始状态的新实例。

在切换时创建新的组件实例通常是有意义的,但在这个例子中,我们的确想要组件能在被“切走”的时候保留它们的状态。要解决这个问题,我们可以用 <KeepAlive> 内置组件将这些动态组件包装起来:

<!-- 非活跃的组件将会被缓存! -->
<KeepAlive>
  <component :is="activeComponent" />
</KeepAlive>

DOM 内模板open in new window中使用时,它应该被写为 <keep-alive>

包含/排除

<KeepAlive> 默认会缓存内部的所有组件实例,但我们可以通过 includeexclude prop 来定制该行为。这两个 prop 的值都可以是一个以英文逗号分隔的字符串、一个正则表达式,或是包含这两种类型的一个数组:

<!-- 以英文逗号分隔的字符串 -->
<KeepAlive include="a,b">
  <component :is="view" />
</KeepAlive>

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

<!-- 数组 (需使用 `v-bind`) -->
<KeepAlive :include="['a', 'b']">
  <component :is="view" />
</KeepAlive>

它会根据组件的 nameopen in new window 选项进行匹配,所以组件如果想要条件性地被 KeepAlive 缓存,就必须显式声明一个 name 选项。

最大缓存实例数

我们可以通过传入 max prop 来限制可被缓存的最大组件实例数。<KeepAlive> 的行为在指定了 max 后类似一个 LRU 缓存open in new window:如果缓存的实例数量即将超过指定的那个最大数量,则最久没有被访问的缓存实例将被销毁,以便为新的实例腾出空间。

<KeepAlive :max="10">
  <component :is="activeComponent" />
</KeepAlive>