与 2.x 版本生命周期相对应的组合式 API

beforeCreate -> 使用 setup()

created -> 使用 setup()

beforeMount -> onBeforeMount

mounted -> onMounted

beforeUpdate -> onBeforeUpdate

updated -> onUpdated

beforeDestroy -> onBeforeUnmount

destroyed -> onUnmounted

errorCaptured -> onErrorCaptured

新增的钩子函数

除了和 2.x 生命周期等效项之外,组合式 API 还提供了以下调试钩子函数:

onRenderTracked

onRenderTriggered

两个钩子函数都接收一个 DebuggerEvent,与 watchEffect 参数选项中的 onTrack 和 onTrigger 类似:

export default {
  onRenderTriggered(e) {
    debugger
    // 检查哪个依赖性导致组件重新渲染
  },
}

生命周期的执行顺序

<template>
  <div></div>
</template>

<script>
  import {reactive,toRefs,watchEffect,onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted , onErrorCaptured} from 'vue'
  export default {
    name: 'App',
    setup(){
      const state = reactive({
        num:0
      })
      console.log('setup!')
      watchEffect(()=>{
        console.log('watchEffect!')
      })
      onBeforeMount(()=>{
        console.log('onBeforeMount!')
      })
      onMounted(() => {
        console.log('onMounted!')
      })
      onBeforeUpdate(()=>{
       console.log('onBeforeUpdate!')
      })
      onUpdated(() => {
        console.log('onUpdated!')
      })
      onBeforeUnmount(()=>{
        console.log('onBeforeUnmount!')
      })
      onUnmounted(() => {
        console.log('onUnmounted!')
      })
      onErrorCaptured(()=>{
        console.log('onErrorCaptured')
      })
      return {
        ...toRefs(state)
      }
    }
  }
</script>

以上执行结果为

setup!
watchEffect!
onBeforeMount!
onMounted!

在数据更新下

<template>
  <div>{{num}}</div>
</template>

<script>
  import {reactive,toRefs,watchEffect,onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted , onErrorCaptured} from 'vue'
  export default {
    name: 'App',
    setup(){
      const state = reactive({
        num:0
      })
      console.log('setup!')
      watchEffect(()=>{
        console.log('watchEffect!')
      })
      onBeforeMount(()=>{
        console.log('onBeforeMount!')
      })
      onMounted(() => {
        console.log('onMounted!')
      })
      onBeforeUpdate(()=>{
       console.log('onBeforeUpdate!')
      })
      onUpdated(() => {
        console.log('onUpdated!')
      })
      onBeforeUnmount(()=>{
        console.log('onBeforeUnmount!')
      })
      onUnmounted(() => {
        console.log('onUnmounted!')
      })
      onErrorCaptured(()=>{
        console.log('onErrorCaptured')
      })

      setTimeout(()=>{
        state.num +=1;
      },500)
      return {
        ...toRefs(state)
      }
    }
  }
</script>

结果

setup!
watchEffect!
onBeforeMount!
onMounted!
// 500ms后
onBeforeUpdate!
onUpdated!

在数据更新且数据未绑定在页面下

<template>
  <div></div>
</template>

<script>
  import {reactive,toRefs,watchEffect,onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted , onErrorCaptured} from 'vue'
  export default {
    name: 'App',
    setup(){
      const state = reactive({
        num:0
      })
      console.log('setup!')
      watchEffect(()=>{
        console.log('watchEffect!')
      })
      onBeforeMount(()=>{
        console.log('onBeforeMount!')
      })
      onMounted(() => {
        console.log('onMounted!')
      })
      onBeforeUpdate(()=>{
       console.log('onBeforeUpdate!')
      })
      onUpdated(() => {
        console.log('onUpdated!')
      })
      onBeforeUnmount(()=>{
        console.log('onBeforeUnmount!')
      })
      onUnmounted(() => {
        console.log('onUnmounted!')
      })
      onErrorCaptured(()=>{
        console.log('onErrorCaptured')
      })

      setTimeout(()=>{
        state.num +=1;
      },500)
      return {
        ...toRefs(state)
      }
    }
  }
</script>

结果

setup!
watchEffect!
onBeforeMount!
onMounted!

结论:在数据更新,数据没绑定在视图上,视图不会更新不会触发update生命周期

关于watch与watchEffect

<template>
  <div>{{num}}</div>
</template>

<script>
  import {reactive,toRefs,watchEffect,watch,onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted , onErrorCaptured} from 'vue'
  export default {
    name: 'App',
    setup(){
      const state = reactive({
        num:0
      })
      console.log('setup!')
      watchEffect(()=>{
        console.log('watchEffect!')
      })
      watch(()=>state.num,()=>{
        console.log('watch!')
      })
      onBeforeMount(()=>{
        console.log('onBeforeMount!')
      })
      onMounted(() => {
        console.log('onMounted!')
      })
      onBeforeUpdate(()=>{
       console.log('onBeforeUpdate!')
      })
      onUpdated(() => {
        console.log('onUpdated!')
      })
      onBeforeUnmount(()=>{
        console.log('onBeforeUnmount!')
      })
      onUnmounted(() => {
        console.log('onUnmounted!')
      })
      onErrorCaptured(()=>{
        console.log('onErrorCaptured')
      })

      setTimeOut(()=>{
        state.num +=1;
      },500)
      return {
        ...toRefs(state)
      }
    }
  }
</script>

结果

setup!
watchEffect!
onBeforeMount!
onMounted!
// 500ms后
watch!
onBeforeUpdate!
onUpdated!

上面的结果会发现,更新state的值时,触发了watch,但是并没有触发watchEffect,接下来看下面例子

<template>
  <div>{{num}}</div>
</template>

<script>
  import {reactive,toRefs,watchEffect,watch,onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted , onErrorCaptured} from 'vue'
  export default {
    name: 'App',
    setup(){
      const state = reactive({
        num:0
      })
      console.log('setup!')
      watchEffect(()=>{
        console.log('watchEffect!')
        console.log(state.num)
      })
      watch(()=>state.num,()=>{
        console.log('watch!')
      })
      onBeforeMount(()=>{
        console.log('onBeforeMount!')
      })
      onMounted(() => {
        console.log('onMounted!')
      })
      onBeforeUpdate(()=>{
       console.log('onBeforeUpdate!')
      })
      onUpdated(() => {
        console.log('onUpdated!')
      })
      onBeforeUnmount(()=>{
        console.log('onBeforeUnmount!')
      })
      onUnmounted(() => {
        console.log('onUnmounted!')
      })
      onErrorCaptured(()=>{
        console.log('onErrorCaptured')
      })

      setTimeout(()=>{
        state.num +=1;
      },500)
      return {
        ...toRefs(state)
      }
    }
  }
</script>

结果

setup!
watchEffect!
0
onBeforeMount!
onMounted!
watchEffect!
1
watch!
onBeforeUpdate!
onUpdated!

以上结果,发现在watchEffect中含有get state中的值,便会触发,没有get state的值是不会触发的

并且watchEffect比watch更先执行

watchEffect的options

<template>
  <div>{{num}}</div>
</template>
<script>
  import {reactive,toRefs,watchEffect,watch,onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted , onErrorCaptured} from 'vue'
  export default {
    name: 'App',
    setup(){
      const state = reactive({
        num:0
      })
      console.log('setup!')
      watchEffect(()=>{
        console.log('watchEffect!')
        console.log(state.num)
      },{
        flush: 'post'
      })
      watch(()=>state.num,()=>{
        console.log('watch!')
      })
      onBeforeMount(()=>{
        console.log('onBeforeMount!')
      })
      onMounted(() => {
        console.log('onMounted!')
      })
      onBeforeUpdate(()=>{
       console.log('onBeforeUpdate!')
      })
      onUpdated(() => {
        console.log('onUpdated!')
      })

      setTimeout(()=>{
        state.num +=1;
      },500)
      return {
        ...toRefs(state)
      }
    }
  }
</script>

结果

setup!
onBeforeMount!
watchEffect!
0
onMounted!
watch!
onBeforeUpdate!
watchEffect!
1
onUpdated!

当flush为post的时候,watchEffect执行会在watch与onBeforeUpdate之后onUpdated之前

flush: 'sync’同步运行

flush: ‘pre’ 组件更新前执行

onBeforeUnmount onUnmounted

父组件

<template>
  <div v-if="show">
    <Children></Children>
  </div>
</template>

<script>
  import {reactive,toRefs} from 'vue'
  import Children from "./components/Children";
  export default {
    name: 'App',
    components: {
      Children
    },
    setup(){
      const state = reactive({
        show: true
      })

      setTimeout(()=>{
        state.show = false;
      },500)
      return {
        ...toRefs(state)
      }
    }
  }
</script>

子组件

<template>
    <div>子组件</div>
</template>

<script>
    import {watchEffect,onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted , onErrorCaptured} from 'vue'

    export default {
        name: "Children",
        setup(){
            console.log('setup!')
            watchEffect(()=>{
                console.log('watchEffect!')
            })
            onBeforeMount(()=>{
                console.log('onBeforeMount!')
            })
            onMounted(() => {
                console.log('onMounted!')
            })
            onBeforeUpdate(()=>{
                console.log('onBeforeUpdate!')
            })
            onUpdated(() => {
                console.log('onUpdated!')
            })
            onBeforeUnmount(()=>{
                console.log('onBeforeUnmount!')
            })
            onUnmounted(() => {
                console.log('onUnmounted!')
            })
            onErrorCaptured(()=>{
                console.log('onErrorCaptured')
            })
        }
    }
</script>

结果

setup!
watchEffect!
onBeforeMount!
onMounted!
onBeforeUnmount!
onUnmounted!

onBeforeUnmount(卸载前)在onUnmounted(卸载后)之前执行

onErrorCaptured

父组件

<template>
  <div>
    <Children></Children>
  </div>
</template>

<script>
  import {onErrorCaptured} from 'vue'
  import Children from "./components/Children";
  export default {
    name: 'App',
    components: {
      Children
    },
    setup(){
      onErrorCaptured(()=>{
        console.log('onErrorCaptured!')
      })
    }
  }
</script>

子组件

<template>
   <div>{{name.title}}</div>
</template>

<script>
    export default {
        name: "Children",
        setup(){
        }
    }
</script>

结果

在子组件引用一个不存在的变量,并取它的子属性,触发报错,父级可以捕获该错误onErrorCaptured(e) 其中e是错误信息,

它也能捕获孙级及其以下的错误,但是,一旦发生错误,代码将停止解析,所以只能捕获致命的第一个错误

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐