vue3 script setup 响应式:核心

  1. ref() ref 对象
  2. computed() 计算属性
  3. reactive() 响应式对象
  4. readonly() 只读对象
  5. watch() watch 侦听器
  6. watchEffect() watchEffect 侦听器
  7. watchPostEffect() watchPostEffect 侦听器
  8. watchSyncEffect() watchSyncEffect
  9. watch()、watchEffect() 的区别

1. ref() ref 对象

(1) 创建一个 ref 对象
(2) 参数:基本数据类型或复杂数据类型(复杂数据类型推荐使用 reactive)
(3) 返回值:一个响应式的、可更改的 ref 对象
(4) 此对象只有一个指向其内部值的属性 .value
(5) 可以为 .value 赋予新的值,它也是响应式的,即所有对 .value 的操作都将被追踪,并且写操作会触发与之相关的副作用

// 导入 ref函数
import { ref } from "vue";

// 创建一个 ref 对象 count
const count = ref<number>(0);
// 获取 count 的值
console.log(count.value);
// 修改 count 的值
count.value++;

2. computed() 计算属性

  1. 只读的计算属性 ref
  • 参数:getter 函数
  • 返回值:一个只读的响应式 ref 对象
  1. 可读可写的计算属性
  • 参数:一个带有 get 和 set 属性的对象
  • 返回值:一个可写的 ref 对象
  1. 通过 .value 获取计算属性的值
  1. 创建一个只读的计算属性
// 导入 ref 、computed 函数
import { ref, computed } from "vue";

// 创建一个只读的计算属性 ref:
const count1 = ref<number>(1);
const plusOne = computed<number>(() => count1.value + 1);

// 获取计算属性 plusOne 的值
console.log(plusOne.value); // 2
// 通过 getter函数 获得的计算属性值具有只读属性,不可修改
plusOne.value++; // 报错
  1. 创建一个可写的计算属性
// 导入 ref 、computed 函数
import { ref, computed } from "vue";

const count2 = ref<number>(1);
const plusTwo = computed<number>({
    // get 属性值的函数需要有返回值,返回值就是该计算属性的 .value
    get: () => count2.value + 1,

    // set 属性值的函数只有在 计算属性 ref 被修改时才会触发
    set: (val) => {
        // val 是上次的 计算属性 的值
        console.log(val); // 10
        count2.value = val + 1;
    },
});
// 修改计算属性,触发 set 属性值的函数
plusTwo.value = 10;

console.log(plusTwo.value); // 12
console.log(count2.value); // 11

3. reactive() 对象的响应式代理

  1. 响应式对象会深层地解包任何 ref 属性,同时保持响应性。
  2. 当访问某个响应式数组或 Map 这样的原生集合类型中的 ref 元素时,不会执行 ref 的解包
  3. 返回的对象以及其中嵌套的对象都会通过 ES Proxy 包裹,因此不等于源对象
  1. 创建一个响应式对象
// 导入 ref 、 reactive 函数
import { ref, reactive } from "vue";
// 导入 Ref 泛型接口
import type { Ref } from "vue";

// 通过 reactive函数 创建一个响应式对象
const obj = reactive<{ count: number }>({
    count: 0,
});
// 可以通过 对象.属性 来获取属性值
console.log(obj.count);

// 通过 ref函数 创建一个响应式对象
const obj1 = ref<{ count: number }>({
    count: 1,
});
// 可以通过 对象.value.属性 来获取属性值
console.log(obj1.value.count);

// 响应式数组
const arr = reactive<Ref<string>[]>([ref("数组")]);
// 使用 数组[下标].value 获取元素的值
console.log(arr[0].value);

// 响应式Map
const map = reactive<Map<string, Ref<number>>>(new Map([["count", ref(0)]]));
// 这里需要 map.get(key).value 获取键值
console.log(map.get("count")?.value);

4. readonly() 只读代理

  1. 接受一个对象 (不论是响应式还是普通的) 或是一个 ref,返回一个原值的只读代理
  2. 只读代理是深层的
  3. 只能读取,不能修改
import { ref, reactive, readonly } from "vue";
import type { Ref } from "vue";

const a1 = reactive<{ count: number }>({ count: 1 });
const copy1 = readonly<{ count: number }>(a1);
// 读取 copy 的属性值
console.log(copy1.count);
// 更改 copy 的属性值 将会失败,并会得到一个警告
copy1.count++; // 警告

const a2 = ref<{ count: number }>({ count: 2 });
const copy2 = readonly<Ref<{ readonly count: number }>>(a2);
// 读取 copy 的属性值
console.log(copy2.value.count);
// 更改 copy 的属性值 将会失败,并会得到一个警告
copy2.value.count++; // 警告

const a3: { count: number } = { count: 3 };
const copy3 = readonly<{ count: number }>(a3);
// 读取 copy 的属性值
console.log(copy3.count);
// 更改 copy 的属性值 将会失败,并会得到一个警告
copy3.count++; // 警告

5. watch() 侦听器

  1. 默认懒监听,只有当侦听源发生改变才会触发
  2. 参数一:侦听器的源。这个来源可以是以下几种:
  • 一个函数,返回一个值
  • 一个 ref
  • 一个响应式对象
  • …或是由以上类型的值组成的数组
  1. 参数二:发生变化时要调用的回调函数,回调函数接受三个参数
  • 回调函数参数一:新值
  • 回调函数参数二:旧值
  • 回调函数参数三:用于注册副作用清理的回调函数
  • 当侦听多个来源时,回调函数接受两个数组,分别对应来源数组中的新值和旧值。
  1. 参数三:可选,配置对象,支持以下这些选项
  • immediate:在侦听器创建时立即触发回调。第一次调用时旧值是 undefined。
  • deep:如果源是对象,强制深度遍历,以便在深层级变更时触发回调。
  • flush:调整回调函数的刷新时机。
  • onTrack / onTrigger:调试侦听器的依赖。
import { ref, watch } from "vue";

const count = ref<number>(0);

watch(
    count, // 侦听的源
    (newValue, oldValue) => {
        // newValue:改变后的源值, oldValue:改变前的源值
        console.log("新旧值", newValue, oldValue);
    },
    {
        immediate: true, // 创建时立即触发调用
        deep: true, // 深层侦听
        // 'sync':源改变后立即调用,'post': 延迟到组件渲染后调用
        flush: "post",
    }
);

6. watchEffect() 立即执行一次的侦听器

  1. 与 watch 侦听器功能相似。 watch 函数默认情况下初始化时不调用; watchEffect 侦听器默认情况下会在初始化时调用一次
  2. 默认情况下,watchEffect 侦听器会在组件渲染之前执行一次
  3. 依赖更改时会被调用一次
  4. 参数、返回值
  • 参数一:必需,函数,要运行的副作用函数
  • 参数一的参数:可选,函数,用来注册清理回调
  • 参数二:可选,对象,用来配置 调整副作用的刷新时机或调试副作用的依赖
  • 返回值:函数,用来停止该副作用的函数
import { ref, reactive, watchEffect } from "vue";

const count = ref<number>(0);

// 默认情况下,侦听器将在组件渲染之前,立即运行一次
const stop = watchEffect(() => {
    console.log(count.value); // -> 输出 0
});

// 监听到依赖改变,侦听器stop 重新执行一次
count.value++; // -> 输出 1

// 清除侦听器stop
stop();
// 参数二:配置对象,用来调整副作用的刷新时机或调试副作用的依赖
const stop2 = watchEffect(() => {}, {
    flush: "post", // 侦听器延迟到组件渲染之后再执行
    onTrack(e) {
        debugger;
    },
    onTrigger(e) {
        debugger;
    },
});

stop2();

7. watchPostEffect()

  • watchEffect() 使用 flush: ‘post’ 选项时的别名
  • 只执行一次,等组件渲染之后执行一次
import { ref, watchPostEffect } from "vue";

const count = ref<number>(0);

watchPostEffect(() => {
    console.log("post", count.value);
});

// 依赖改变,触发侦听器
count.value++;

8. watchSyncEffect()

  • watchEffect() 使用 flush: ‘sync’ 选项时的别名
  • 会执行两次,初始化时调用一次,依赖发生改变时立即调用一次
import { ref, watchSyncEffect } from "vue";

const count = ref<number>(0);

watchSyncEffect(() => {
    // 组件初始化时,触发一次侦听器
    console.log("Sync", count.value);
});

// 依赖改变,触发侦听器
count.value++;

9. watch、watchEffect 的区别

  1. 侦听源发生变化,触发回调函数
    • watch 只追踪明确侦听的数据源,不会追踪在回调中访问到的东西
    • watchEffect 会在副作用发生期间追踪依赖。会在同步执行过程中,自动追踪所有能访问到的响应式属性。
    • 只要是 侦听的函数内部的变量 发生变化就会触发
    • watch 可以输出侦听源变化前后的值
    • watchEffect 不行
    • watch 是 Vue2 的 API ,Vue3 中也保留了该 API
    • watchEffect 是 Vue3 中新增的 API
    • watch 默认情况下,组件初始化时不调用
    • watchEffect 默认情况下,组件初始化时调用一次
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值