Skip to content
当前页大纲

keep-alive

keep-aliveVue内置的一个组件,可以实现组件缓存,当组件切换时不会对当前组件进行卸载

activateddeactivated两个生命周期,将会在<keep-alive>树内的所有嵌套组件中触发,用来得知当前组件是否处于活跃状态

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

实现原理:

data为什么必须是一个函数

为什么组件中的data必须是一个函数,然后return一个对象,而new Vue实例里,data可以直接是一个对象?

因为组件是用来复用的,且 JS 里对象是引用关系,如果组件中data是一个对象,那么这样作用域没有隔离,子组件中的data属性值会相互影响,如果组件中data选项是一个函数,那么每个实例可以维护一份被返回对象的独立的拷贝,组件实例之间的data属性值不会互相影响;而new Vue的实例,是不会被复用的,因此不存在引用对象的问题

父子组件钩子函数执行顺序

Vue的父组件和子组件生命周期钩子函数执行顺序可以归类为以下 4 部分:

  • 加载渲染过程:父 beforeCreate -> 父 created -> 父 beforeMount -> 子 beforeCreate -> 子 created -> 子 beforeMount -> 子 mounted -> 父 mounted

  • 子组件更新过程:父 beforeUpdate -> 子 beforeUpdate -> 子 updated -> 父 updated

  • 父组件更新过程:父 beforeUpdate -> 父 updated

  • 销毁过程:父 beforeDestroy -> 子 beforeDestroy -> 子 destroyed -> 父 destroyed

父组件监听子组件的生命周期

比如有父组件Parent和子组件Child,如果父组件监听到子组件挂载mounted就做一些逻辑处理,可以通过自定义事件的方式来实现:

vue
<template>
  <Child @mounted="doSomething" />
</template>
<script>
export default {
  methods: {
    doSomething() {}
  }
}
</script>
vue
<script>
export default {
  mounted() {
    this.$emit('mounted')
  }
}
</script>

自定义事件的方式太Low了,我们来换一种更简单优雅的方式。可以在父组件引用子组件时通过@hook来监听即可,如下所示:

vue
<template>
  <Child @hook:mounted="doSomething" />
</template>
<script>
export default {
  methods: {
    doSomething() {}
  }
}
</script>

当然@hook方法不仅仅是可以监听mounted,其它的生命周期事件,例如:createdupdated等都可以监听

其实这就是个语法糖,只是官方 API 文档中没有写出来而已,具体的源码如下:

ts
export function callHook(vm: Component, hook: string, args?: any[], setContext = true) {
  // #7573 disable dep collection when invoking lifecycle hooks
  pushTarget()
  const prev = currentInstance
  setContext && setCurrentInstance(vm)
  const handlers = vm.$options[hook]
  const info = `${hook} hook`
  if (handlers) {
    for (let i = 0, j = handlers.length; i < j; i++) {
      invokeWithErrorHandling(handlers[i], vm, args || null, vm, info)
    }
  }
  if (vm._hasHookEvent) {
    vm.$emit('hook:' + hook)
  }
  setContext && setCurrentInstance(prev)
  popTarget()
}

MIT License.