vue/组件化/keep-alive

65 阅读1分钟

作用

动态切换组件,又想保存组件的状态,除了使用v-show,还可以使用keep-alive组件。

KeepAlive 组件可以避免一个组件被频繁地销毁/重建。

原理

KeepAlive 的本质是缓存管理,再加上特殊的挂载/卸载逻辑。

将被 KeepAlive 的组件从原容器搬运到另外一个隐藏的容器中,实现“假卸载”。当被搬运到隐藏容器中的组件需要再次被“挂载”时,我们也不能执行真正的挂载逻辑,而应该把该组件从隐藏容器中再搬运到原容器。这个过程对应到组件的生命周期,其实就是 activated 和 deactivated。

同时:为了避免无限缓存组件导致消耗很多内存,keepAlive可以设置一个缓存组件的数量值,使用了“最新一次的访问”策略算法。用一个队列来缓存组件,最新的访问的组件进队列,队列满的时候,队头组件出队列。

api说明

keep-alive有以下三个属性:

  • include 字符串或正则表达式,只有名称匹配的组件会被匹配;
  • exclude 字符串或正则表达式,任何名称匹配的组件都不会被缓存;
  • max 数字,最多可以缓存多少组件实例。
  • 多个子组件,只渲染第一个。

component有以下一个属性

  • is 表示当与组件的name一致时,加载这个组件

测试代码

TheMain.vue

<template>
  <div class="MainWrapper">
    <div style="position:absolute;font-size:50px;right:50%" @click="changeKeepAliveComponent"  >切换</div>
    <keep-alive >
      <component :is="keepAliveName"></component>
    </keep-alive>
  </div>
</template>

<script>
// 引入组件
import BaseTest1 from "@/components/BaseTest1";
import BaseTest2 from "@/components/BaseTest2";

export default {
  components: {
    BaseTest1,
    BaseTest2,
  },
  data() {
    return {
      isShow:false,
      keepAliveName:'BaseTest1',
    };
  },
  created() {},
  methods:{
    changeKeepAliveComponent(){
      this.keepAliveName = this.keepAliveName == 'BaseTest1' ? 'BaseTest2' : 'BaseTest1'
    }
  },
};
</script>

<style lang="less" scoped>
@rpx: 7.5vw;
.MainWrapper {
  position: fixed;
  width: 100vw;
  height: 100vh;
  background-color: white;
}
</style>

BaseTest1.vue

<template>
  <div style="position:absolute;font-size:50px" @click="num++">{{ num }}</div>
</template>
<script>
export default {
  name: "BaseTest1",
  props: {
    src: String,
  },
  data() {
    return {
      num: 0,
    };
  },
  mounted() {
    console.log("mounted-test1");
  },
};
</script>

BaseTest2.vue

<template>
  <div style="position:absolute;font-size:50px;right:0" @click="num++">
    {{ num }}
  </div>
</template>
<script>
export default {
  name: "BaseTest2",
  props: {
    src: String,
  },
  data() {
    return {
      num: 0,
    };
  },
  mounted() {
    console.log("mounted-test2");
  },
};
</script>