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

2022年6月9日13:47:14

一、生命周期

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函数

  • 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>

三、toRef 与 toRefs

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>
  • 作者:JHY97
  • 原文链接:https://blog.csdn.net/JHY97/article/details/124726176
    更新时间:2022年6月9日13:47:14 ,共 4685 字。