vue3setup和生命周期

3,957 阅读4分钟

setup函数的特性

  • 使用Composition API 的入口
  • 在beforeCreate之前调用
  • 在setup中没有this
  • 返回对象中的属性刻在模板中使用
  • setup函数是处于生命周期函数 beforeCreate 和 Created 两个钩子函数之间的函数 也就说在 setup函数中是无法 使用 data 和 methods 中的数据和方法的
  • setup函数是 Composition API(组合API)的入口
  • 在setup函数中定义的变量和方法最后都是需要 return 出去的 不然无法再模板中使用

setup定义变量及方法ref和reactive

ref接受一个内部值并返回一个响应式且可变的 ref 对象。ref 对象具有指向内部值的单个 property .value

reactive是返回对象的响应式副本

1、简单数据类型(String、Number等)推荐使用ref

引入: import { ref } from 'vue' 使用:let count = ref(1); 后面想改变或获取值,通过count.value进行

2、复杂数据类型(Array、Object)推荐使用reactive

引入: import { reactive } from 'vue' 使用: let arr = reactive({ age:18 }),传入一个对象,vue会封装成Proxy对象,使用里面的方法实现响应式数据

注意:如果不需要做响应式的数据,比如从接口获取的数据,直接声明变量存放即可,不需要调用ref或者reactive

上代码:

<template>
  <div class="word">
    <div>ref:{{ count }}</div>
    <button @click="addRefFun">点击ref自增</button>
    <div>reactive:{{ state.reactivelist }}</div>
    <div>reactive数组:{{ state.arr }}</div>
    <button @click="addReactiveFun">点击reactive自增</button>
  </div>
</template>

<script>
import { reactive, ref, toRef } from "vue";
export default {
  components: {},
  setup() {
    const count = ref(1);
    const state = reactive({
      reactivelist: 1,
      arr: [1, 2],
    });
    const addRefFun = () => {
      count.value++;
    };
    const addReactiveFun = () => {
      state.reactivelist++;
      state.arr.push(3, 4, 5);
    };
    let age = toRef(state, "age");
    state.age = 1;

    console.log(state);
    return {
      count,
      state,
      age,
      addRefFun,
      addReactiveFun,
    };
  },
};
</script>

说了那么多,其实我们一直都在做同一件事情,那就是双向数据绑定。vue一共提供了两种数据响应式监听,这就有点React Hooks的味道了。ref 函数传入一个值作为参数,返回一个基于该值的响应式Ref对象,该对象中的值一旦被改变和访问,都会被跟踪到,就像我们改写后的示例代码一样,通过修改 count.value 的值,可以触发模板的重新渲染,显示最新的值。 其实,除了 ref 函数,Vue3.0中还提供了另外一个可以创建响应式对象的函数,那就是 reactive 函数。

为什么要同时提供这两个API呢?下面来说一说。

1.是为了适应不同的写法的人群

有人喜欢这种的写法:

const a = 1
const b = 2

也有人喜欢这种的写法:

const field = {
  a : 1,
  b : 1    
}

怎么样的写法,看自己跟人。这两种风格的代码都是没有问题。关键在于个人的偏好。

2.ref只可以监听简单的数据,而reactive可以监听所有的数据

ref这种写法简单,但也有弊端,经过尝试,我发现他只能监听一些如数字、字符串、布尔之类的简单数据。而一些复杂的数据或者是对象我们可以用reactive来实现

3.使用的方式不一样

1、ref修改数据需要使用这样count.value=xxx的形式,而reactive只需要state.reactiveField=值这样来使用

2、第二点体现在template中引用时候为reactiveField,不需要state,也就是说我reactive对象里面字段是应该直接使用的

3、体现在reactive在return时候需要toRefs来转换成响应式对象

ref和reactive区别:

  1. 如果在template里使用的是ref类型的数据, 那么Vue会自动帮我们添加.value
  2. 如果在template里使用的是reactive类型的数据, 那么Vue不会自动帮我们添加.value

我门可以通过isRef / isReactive 方法来判断数据到底是ref还是reactive

setup声明周期

从'vue'中引入的生命周期函数,这些生命周期钩子注册函数只能在setup()期间同步使用 因为它们依赖于内部的全局状态来定位当前组件实例(正在调用setup()的组件实例),不在当前组件下调用这些函数会抛出一个错误。 即可以从其他文件引入使用了生命周期的函数等,放在setup中执行

和外部的生命周期函数相比,会优先指向setUp内的生命周期函数,再去执行外部的生命周期函数

vue2.0vue3.0
beforeCreatesetup
beforeCreatesetup
createdsetup
beforeMount(挂载前)onBeforeMount
mounted(挂载后)onMounted
beforeUpdate(数据更新前)onBeforeUpdate
updated(数据更新后)onUpdated
beforeDestroy(销毁前)onBeforeUnmount
destroyed(销毁后)onUnmounted

<script>
import {
  onBeforeMount,
  onMounted,
  onBeforeUpdate,
  onUpdated,
  onBeforeUnmount,
  onUnmounted,
  onRenderTracked,
  onRenderTriggered,
} from "vue";
export default {
  components: {},
  data() {
    return {};
  },
  setup() {
    // setup里面存着两个生命周期创建前和创建后

    // beforeCreate
    // created

    onBeforeMount(() => {
      console.log("onBefore   ====>  vue2.0 x beforemount");
    });
    onMounted(() => {
      console.log("onMounted  ====>  vue2.0 x mount");
    });
    onBeforeUpdate(() => {
      console.log("onBeforeUpdate  ====>  vue2.0 x beforeUpdate");
    });
    onUpdated(() => {
      console.log("onUpdated  ====>  vue2.0 x update");
    });
    onBeforeUnmount(() => {
      //在卸载组件实例之前调用。在这个阶段,实例仍然是完全正常的。
      console.log("onBeforeUnmount ====>  vue2.0 x beforeDestroy");
    });
    onUnmounted(() => {
      //卸载组件实例后调用,调用此钩子时,组件实例的所有指令都被解除绑定,所有事件侦听器都被移除,所有子组件实例被卸载。
      console.log("onUnmounted ====>  vue2.0 x destroyed");
    });
    // 新增两个生命周期函数
    //每次渲染后重新收集响应式依赖
    onRenderTracked(({ key, target, type }) => {
      // 跟踪虚拟DOM重新渲染时调用,钩子接收debugger event作为参数,此事件告诉你哪个操作跟踪了组件以及该操作的目标对象和键。
      // type:set/get操作
      // key:追踪的键
      // target:重新渲染后的键
      console.log("onRenderTracked");
    });
    //每次触发页面重新渲染时自动执行
    onRenderTriggered(({ key, target, type }) => {
      //当虚拟DOM重新渲染被触发时调用,和renderTracked类似,接收debugger event作为参数,
      // 此事件告诉你是什么操作触发了重新渲染,以及该操作的目标对象和键
      console.log("onRenderTriggered");
    });
    return {};
  },
};
</script>

相关链接