keep-alive原理

文章目录

      • 什么是keep-alive?
      • 用法
      • activated和deactivated两个钩子函数
      • 实现原理

什么是keep-alive?

keep-alive是vue中的一个内置组件,能够把不活动的组件保存到缓存当中,而不是直接销毁他,其实是一个抽象的组件,不会渲染到真实dom中,页不会出现在父组件链中,作用是提供给路由切换用的。
提供include与exclude两个属性,允许组件有条件进行缓存。

作用:减少不必要的请求,节约网络资源,解决页面重新渲染切换闪动问题。用来切换页面的时候保存状态。

用法

1、用在动态组件中
类似tab切换,路径是不会改变的,

// App.vue


2、用在vue-router中

// router.js
const routes = [
  {
    path: '/',
    name: 'home',
    component: Home,
    meta: { // 给每个路由添加属性
      keepAlive: true
    }
  },
  {
    path: '/about',
    name: 'about',
    component: () => import(/* webpackChunkName: "about" */ '../views/About.vue'),
    meta: { // 给每个组件添加属性
      keepAlive: false
    }
  }
]


// App.vue
home
about

    


// 或者
 

   
  

activated和deactivated两个钩子函数

keep-alive切换时,会触发自己的activated和deactivated两个钩子函数,可以理解为vue的created和destroyed两个钩子

// home.vue






实现原理

其实就是在created时将需要缓存的VNode节点保存在this.cache中,在render时,如果VNode的name符合在缓存条件(可以用include以及exclude控制),则会从this.cache中取出之前缓存的VNode实例进行渲染。
keep-alive原理_第1张图片

// App.vue



// sKeepAlive/index.js
import Vue from 'vue'
const sKeepAlive = Vue.component('s-keep-alive', {
  name: 'keep-alive',
  abstract: true,
  props: {
    include: String,
    exclude: String,
    max: [String, Number]
  },
  created () {
    this.cache = Object.create(null)
    this.keys = []
    console.log(this.cache)
    console.log(this.keys)
  },
  destroyed () {
  },
  mounted () {
    // var this$1 = this
    this.$watch('include', function (val) {
      // pruneCache(this$1, function (name) { return matches(val, name) })
    })
    this.$watch('exclude', function (val) {
      // pruneCache(this$1, function (name) { return !matches(val, name) })
    })
  },
  // jxs用法
  render (h) {
    var slot = this.$slots.default
    var vnode = getFirstComponentChild(slot)
    // console.log(vnode)
    var componentOptions = vnode && vnode.componentOptions
    if (componentOptions) {
      var ref$1 = this
      var cache = ref$1.cache
      var keys = ref$1.keys
      var key = vnode.key == null
        ? componentOptions.Ctor.cid + (componentOptions.tag ? ('::' + (componentOptions.tag)) : '')
        : vnode.key
      // console.log(key)
      // 如果已经做过缓存了则直接从缓存中获取组件实例给vnode,还未缓存过则进行缓存
      if (cache[key]) {
        vnode.componentInstance = cache[key].componentInstance
        keys.push(key)
      } else {
        cache[key] = vnode
        keys.push(key)
      }
      vnode.data.keepAlive = true // 加标签,渲染的时候判断是否为true,true的话不再进入$mount过程,即生命周期的钩子函数都不会被触发
    }
    return vnode || (slot && slot[0]) // 返回vnode
  }
})

function getFirstComponentChild (children) {
  if (Array.isArray(children)) {
    for (var i = 0; i < children.length; i++) {
      var c = children[i]
      if (isDef(c) && (isDef(c.componentOptions) || isAsyncPlaceholder(c))) {
        return c
      }
    }
  }
}

function isDef (v) {
  return v !== undefined && v !== null
}

function isAsyncPlaceholder (node) {
  return node.isComment && node.asyncFactory
}

export default sKeepAlive

源码参考

你可能感兴趣的:(vue)