Vue3知识点整理 常用Composition API(3)- 生命周期、自定义hook、toRef

首页 / 新闻资讯 / 正文

一、生命周期

Vue2.x生命周期相关:Vue知识点整理(一)- Vue核心(6)- 生命周期(重要)

Vue2官方文档 - 生命周期钩子

1.1 Vue3 生命周期图示

官方Vue3生命周期图示

1.2 Vue3.0中生命周期钩子

Vue3.0中可以继续使用Vue2.x中的生命周期钩子,但有有两个被更名:

  • beforeDestroy 改名为 beforeUnmount
  • destroyed 改名为 unmounted

简单案例练习

  • 创建一个组件Demo.vue,并定义一个sum属性,添加点击事件更新sum的内容
  • Demo.vue 内添加生命周期钩子,并在控制台输出
  • App.vue中引入Demo组件,并使用v-if API 和 添加点击事件控制 Demo组件 显示和隐藏

效果展示

相关代码:

Demo.vue

<template>   <h2>当前求和为:{{ sum }}</h2>   <button @click="sum++">点击+1</button> </template>  <script> import { ref } from "vue"; export default {   name: "Demo",   setup() {     console.log("-----setup-----");     // 数据     let sum = ref(0);      return {       sum,     };   },   beforeCreate() {     console.log("-----beforeCreate-----");   },   created() {     console.log("-----created-----");   },   beforeMount() {     console.log("-----beforeMount-----");   },   mounted() {     console.log("-----mounted-----");   },   beforeUpdate() {     console.log("-----beforeUpdate-----");   },   updated() {     console.log("-----updated-----");   },   beforeUnmount() {     console.log("-----beforeUnmount-----");   },   unmounted() {     console.log("-----unmounted-----");   }, }; </script>  <style></style>

App.vue

<template>   <button @click="isShowDemo = !isShowDemo">控制Demo组件显示/隐藏</button>   <Demo v-if="isShowDemo"></Demo> </template>  <script> import Demo from "./components/Demo.vue"; import { ref } from "vue"; export default {   name: "App",   components: { Demo },   setup() {     let isShowDemo = ref(true);      return { isShowDemo };   }, }; </script>

1.3 Composition API 形式的生命周期钩子

Vue3官方文档 - 组合式API - 生命周期钩子

Vue3.0也提供了 Composition API 形式的生命周期钩子,与Vue2.x中钩子对应关系如下:

setup () 内部调用生命周期钩子
选项式 API Hook insidesetup
beforeCreate Not needed*
created Not needed*
beforeMount onBeforeMount
mounted onMounted
beforeUpdate onBeforeUpdate
updated onUpdated
beforeUnmount onBeforeUnmount
unmounted onUnmounted
errorCaptured onErrorCaptured
renderTracked onRenderTracked
renderTriggered onRenderTriggered
activated onActivated
deactivated onDeactivated

TIP:

  • 因为setup 是围绕beforeCreatecreated 生命周期钩子运行的,所以不需要显式地定义它们。换句话说,在这些钩子中编写的任何代码都应该直接在setup 函数中编写。

简单案例练习

  • 创建一个组件Demo.vue,并定义一个sum属性,添加点击事件更新sum的内容
  • Demo.vue 中setup函数中添加 Composition API 形式的生命周期钩子,并在控制台输出
  • App.vue中引入Demo组件,并使用v-if API 和 添加点击事件控制 Demo组件 显示和隐藏

效果展示

 仅需修改Demo.vue中相关代码即可

<script> import {   ref,   onBeforeMount,   onMounted,   onBeforeUpdate,   onUpdated,   onBeforeUnmount,   onUnmounted, } from "vue"; export default {   name: "Demo",   setup() {     console.log("-----setup-----");     // 数据     let sum = ref(0);      onBeforeMount(() => {       console.log("-----onBeforeMount-----");     });     onMounted(() => {       console.log("-----onMounted-----");     });     onBeforeUpdate(() => {       console.log("-----onBeforeUpdate-----");     });     onUpdated(() => {       console.log("-----onUpdated-----");     });     onBeforeUnmount(() => {       console.log("-----onBeforeUnmount-----");     });     onUnmounted(() => {       console.log("-----onUnmounted-----");     });      return { sum };   }, }; </script>

  • hook:本质是一个函数,把setup函数中使用的 Composition API进行封装
  • 类似于Vue2.x中的minxin
  • 自定义hook的优势:复用代码,让setup中的逻辑更清楚易懂

简单案例练习

  • 在hooks文件夹下创建一个usePoint.js文件,并在其内编写鼠标点击事件,并获取相关坐标的方法与数据
  • 在Demo.vue组件内引用 usePoint.js
  • 在Demo组件隐藏后,usePoint 不生效

usePoint.js

import { reactive, onMounted, onBeforeUnmount } from "vue"; export default function () {   // 实现鼠标"打点"相关的数据   let point = reactive({     x: 0,     y: 0,   });    // 实现鼠标"打点"相关的方法   function savePoint(event) {     point.x = event.pageX;     point.y = event.pageY;     console.log(event.pageX, event.pageY);   }    //   实现鼠标"打点"相关的生命周期钩子   onMounted(() => {     window.addEventListener("click", savePoint);   });    onBeforeUnmount(() => {     window.removeEventListener("click", savePoint);   });    return point; }

Demo.vue

<template>   <h2>当前求和为:{{ sum }}</h2>   <button @click="sum++">点击+1</button>   <hr />   <h2>当前点击时鼠标的坐标为:x:{{ point.x }}, y:{{ point.y }}</h2> </template>  <script> import { ref } from "vue"; import usePoint from "../hooks/usePoint"; export default {   name: "Demo",   setup() {     // 数据     let sum = ref(0);     let point = usePoint();     return { sum, point };   }, }; </script>

Vue3官方文档 - toRef

Vue3官方文档 - toRefs

3.1 作用

创建一个ref对象,其value值指向另一个对象中的某个属性

3.2 语法

const fooRef = toRef(state, 'foo')

3.3 应用

要将响应式对象中的某个属性单独提供给外部使用时

3.4 扩展

toRefs 与 toRef 功能一致,但可以批量创建多个ref对象,例如

const stateAsRefs = toRefs(state)

3.5 简单案例练习

  • 使用toRef
<template>   <h2>姓名:{{ name }}</h2>   <h2>年龄:{{ age }}</h2>   <h2>零用钱:{{ money }}</h2>   <button @click="name += '!'">姓名添加上!</button>   <button @click="age++">年龄增长</button>   <button @click="money++">零花钱增加</button> </template>  <script> import { reactive, toRef } from "vue"; export default {   name: "App",   setup() {     let person = reactive({       name: "周星星",       age: 25,       item: {         wallet: {           money: 100,         },       },     });      return {       // 使用toRef       name: toRef(person, "name"),       age: toRef(person, "age"),       money: toRef(person.item.wallet, "money"),     };   }, }; </script>
  • 使用toRefs
<template>   <h2>姓名:{{ name }}</h2>   <h2>年龄:{{ age }}</h2>   <h2>零用钱:{{ item.wallet.money }}</h2>   <button @click="name += '!'">姓名添加上!</button>   <button @click="age++">年龄增长</button>   <button @click="item.wallet.money++">零花钱增加</button> </template>  <script> import { reactive, toRef, toRefs } from "vue"; export default {   name: "App",   setup() {     let person = reactive({       name: "周星星",       age: 25,       item: {         wallet: {           money: 100,         },       },     });      return {       // 使用toRef       // name: toRef(person, "name"),       // age: toRef(person, "age"),       // money: toRef(person.item.wallet, "money"),        // 使用toRefs       ...toRefs(person),     };   }, }; </script>  <style></style>