温故而知新之:生命周期

作者: 自然框架 | 来源:发表于2021-12-01 17:08 被阅读0次

vue的生命周期还是比较饶腾的,最直接的方法就是都写出来体验一下。

初体验

首先整理 vue3 的生命周期,只考虑在 setup 里面的就好。

import {
  // onBeforeCreate,  // setup 中无效
  // onCreated, // setup 中无效
  onBeforeMount,
  onMounted,
  onBeforeUpdate,
  onUpdated,
  onBeforeUnmount,
  onUnmounted,
  onErrorCaptured,
  onRenderTracked,
  onRenderTriggered,
  onActivated,
  onDeactivated,
  provide,
  inject
} from 'vue'

export default (flag) => {

  // 在挂载开始之前被调用
  onBeforeMount(() => {
    log(`${flag} == onBeforeMount`)
  })

  // 在实例挂载完成后被调用
  onMounted(() => {
    log(`${flag} == onMounted`)
  })

  // 在数据发生改变后,DOM 被更新之前被调用
  onBeforeUpdate(() => {
    log(`${flag} == onBeforeUpdate :`)
  })

  // 在数据更改导致的虚拟 DOM 重新渲染和更新完毕之后被调用
  onUpdated(() => {
    log(`${flag} == onUpdated`)
  })

  // 在卸载组件实例之前调用
  onBeforeUnmount(() => {
    log(`${flag} == onBeforeUnmount`)
  })

  // 卸载组件实例后调用
  onUnmounted(() => {
    log(`${flag} == onUnmounted`)
  })

  // 在捕获一个来自后代组件的错误时被调用
  onErrorCaptured((res) => {
    log(`${flag} == onErrorCaptured :`, res)
  })

  // 跟踪虚拟 DOM 重新渲染时调用
  onRenderTracked((res) => {
    log(`${flag} == onRenderTracked :`, res)
  })

  // 当虚拟 DOM 重新渲染被触发时调用
  onRenderTriggered((res) => {
    log(`${flag} == onRenderTriggered :`, res)
  })

  // 被 keep-alive 缓存的组件激活时调用
  onActivated((res) => {
    log(`${flag} == onActivated :`, res)
  })

  // 被 keep-alive 缓存的组件失活时调用
  onDeactivated((res) => {
    log(`${flag} == onDeactivated :`, res)
  })
}
  • flag 做一个标识,区分不同的组件。

然后我们可以在组件里面引入

  import { lifecycle } from '/nf-ui-core'
  lifecycle('表单页面', true)

这样就可以了。运行项目,可以看到组件的加载过程,更新过程,以及卸载过程。

增加功能

只是看看事件的触发情况,有点单调,我们可以加上一个计时的功能,看看加载、卸载、更新到底需要多长时间。


export default (flag, isTime = false) => {
  
  const t = (isTime) ? 
    logTime(`${flag}***加载用时:`) :
    {end: () => {} }

  let t2 = null
 
  // 在实例挂载完成后被调用
  onMounted(() => {
    log(`${flag} == onMounted`)
    t.end()
  })
  • isTime 是否计时

如果需要计时的话,就加上计时功能,函数开始运行时记个时间,然后在 onMounted 里面再记个时间,然后相减就是加载的时间。

同理我们可以对卸载和更新计时


  // 在数据发生改变后,DOM 被更新之前被调用
  onBeforeUpdate(() => {
    log(`${flag} == onBeforeUpdate :`)
    if (isTime) {
      t2 = logTime(`${flag}***更新 DOM 用时`)
    }
  })

  // 在数据更改导致的虚拟 DOM 重新渲染和更新完毕之后被调用
  onUpdated(() => {
    log(`${flag} == onUpdated`)
    if (isTime) t2.end()
  })

  // 在卸载组件实例之前调用
  onBeforeUnmount(() => {
    log(`${flag} == onBeforeUnmount`)
    if (isTime) {
      t2 = logTime(`${flag}***卸载组件用时`)
    }
  })

  // 卸载组件实例后调用
  onUnmounted(() => {
    log(`${flag} == onUnmounted`)
    if (isTime) t2.end()
  })

计时采用的是 console.time()实现的,只是被我封装了一下。

然后运行组件就可以看到各个环节需要的时间了。

增加父子组件的关系。

组件是有父子关系的,而且有时候会比较复杂,虽然有了一个flag,但是并没有体现父子关系,简单的还好,复杂的就有点不清晰了。

我们可以利用 provide 、inject 来实现父子关系的表达。



const f = Symbol('___nf-liefcycle___')

export default (_flag, isTime = false) => {

  // 判断上级的标识
  const _parentflag = inject(f)
  const flag = (_parentflag) ?
    _parentflag + '----' + _flag :
    _flag

  // 记入标记
  provide(f, flag)
 ...
}

首先定义一个 Symbol 作为标志,然后看看上级组件是否有标记,没有的话就当做父组件,有的话就取出来,然后加上自己的flag,这样一个简单的父子的层级关系就做好了。

看看最终效果。

vue的生命周期

可以看到生命周期的钩子的触发过程,以及使用的时间,可以看看各个组件的渲染效率。

相关文章

网友评论

    本文标题:温故而知新之:生命周期

    本文链接:https://www.haomeiwen.com/subject/etgsxrtx.html