vite+vue3+ts中watch和watchEffect的使用

18 篇文章 1 订阅

vite+vue3+ts中watch和watchEffect的使用

watch

vue官方文档:https://cn.vuejs.org/api/reactivity-core.html#watch
可以监听基础类型,整个对象,对象的某个属性

ref

对于基本数据类型(如字符串、数字),ref 提供了完整的响应式特性

对于对象,ref 也可以使其成为响应式,但 watch 默认不进行深度监听,需要手动指定 deep 选项

ref基础类型:直接监听,可获取新旧值

const num = ref(1);

const changeValue = function () {
  num.value++;
};

watch(num, (newValue, oldValue) => {
  console.log("监听变化", newValue, oldValue);
});
  • ref对象类型:需要显式开启深度监听,但是只能获取新值

需要使用深度监听,由于 JavaScript 对象和数组的引用特性,newValueoldValue 会指向相同的内存地址;因此,在数据变化后,newValueoldValue 是相同的

const count = ref({
  a: 1,
  b: 2,
});

const changeValue = function () {
  count.value.a ++;
};

// 不生效
watch(count, (newValue, oldValue) => {
  console.log("监听变化", newValue, oldValue);
});
// 生效,添加deep
watch(count, (newValue, oldValue) => {
  console.log('监听变化deep', newValue, oldValue)
}, { deep: true })

把watch的引用类型数据源浅拷贝了一份,即可完成对新旧值得获取(多层数据需要使用深拷贝)

watch(
  () => {
    return { ...count.value };
  },
  (newValue, oldValue) => {
    console.log("监听变化deep-return\n", newValue, oldValue);
  },
  { deep: true }
);
  • ref对象的单个属性

此时第一个参数是一个箭头函数

watch(() => count.value.a, (newValue, oldValue) => {
  console.log("监听变化ref单个\n", newValue, oldValue);
});
  • ref数组类型
const list = ref([1, 2, 3, 4, 6]);

const changeValue = function () {
  list.value[0] ++;
};

watch(
  list,
  (newValue, oldValue) => {
    console.log("监听变化list-deep\n", newValue, oldValue);
  },
  { deep: true }
);
  • ref对象数组类型
const list = ref([
  { a: 1, b: 1 },
  { a: 1, b: 1 },
]);

const changeValue = function () {
  list.value[0].a++;
};

watch(
  list,
  (newValue, oldValue) => {
    console.log("监听变化list-deep\n", newValue, oldValue);
  },
  { deep: true }
);

使用深拷贝获取旧值

watch(
  () => JSON.parse(JSON.stringify(list.value)),
  (newValue, oldValue) => {
    console.log("监听变化deep-return\n", newValue, oldValue);
  },
  { deep: true }
);
reactive

reactive 用于创建一个深层次的响应式对象

对于 reactive 对象,watch 默认执行深度监听

  • reactive对象整体:直接监听,只能获取到新值
const demo = reactive({
  name: "aaa",
  item: {
    name: "",
    num: 1,
  },
});

const changeValue = function () {
  demo.item.num++;
};

watch(demo, (newValue, oldValue) => {
  console.log("监听变化reactive\n", newValue, oldValue);
});
  • reactive对象单个属性
watch(() => demo.item.num, (newValue, oldValue) => {
  console.log("监听变化reactive单个\n", newValue, oldValue);
});
props

使用 getter 函数返回值的形式,默认不开启深度监听

  • 父组件
<WatchB :item="demo"></WatchB>

const demo = reactive({
  name: "aaa",
  num: 1,
  item: {
    name: "",
    num: 1,
  },
});
  • 子组件
const props = defineProps(["item"]);

const ite = ref();
ite.value = props.item;

watch(
  () => props.item,
  (newVal, oldVal) => {
    console.log(ite.value);
  },
  { deep: true }
);
immediate

默认情况下watch懒加载的,设置immediate: true时,会在初始化时立即执行回调函数

{ deep: true, immediate: true }
组合监听

在组合监听的情况下,Vue 需要明确知道是否需要对 reactive 对象进行深度监听,所以需要显式开启深度监听

第一个参数是一个数组

watch(
  [() => demo, num],
  ([newDemo, newNum], [oldDemo, oldNum]) => {
    console.log("watch 已触发: demo", newDemo, oldDemo);
    console.log("watch 已触发: num", newNum, oldNum);
  },
  { deep: true }
);

watchEffect

在 watchEffect 的回调中,任何访问的响应式引用都会被追踪,当这些引用的值发生变化时,watchEffect 的回调会自动重新执行

watchEffect 适用于需要自动追踪多个数据源的场景,如副作用操作,用于清理或重置副作用(如定时器、订阅等)

watchEffect默认初始时就会执行第一次,一旦运行就会立即监听,组件卸载的时候会停止监听

watchEffect 无法获取到变化前的值,只能获取变化后的值

vue官方文档:https://cn.vuejs.org/api/reactivity-core.html#watcheffect

单值多值侦听
const number = reactive({ count: 0 });

const countAdd = () => {
  number.count++;
};

watchEffect(()=>{
  console.log("新的值:", number);
})

watchEffect 本身不会进行深度监听,它只会自动跟踪其回调函数中所引用的响应式状态(通过 ref 或 reactive 创建的状态)的变化。如果在 watchEffect 中引用了一个 reactive 对象的某个属性,它只会在那个具体属性发生变化时触发

const demo = reactive({
  name: "aaa",
  num: 1,
  item: {
    name: "",
    num: 1,
  },
});

watchEffect(() => {
  console.log("demo-num的变化后的值\n", demo.item.num);
});

watchEffect 只会在 demo.item.num 发生变化时触发。对于 demodemo.num 的变化,watchEffect 不会响应,因为它没有被 watchEffect 的回调函数所引用

watchEffect(() => {
  console.log("demo的变化后的值\n", demo);
});
副作用
// 副作用
const v3 = ref(3)
watchEffect(()=>{
  const v = v3.value
  // 存在异步
  setTimeout(()=>{
    console.log(v,'timeout')
  },1000);
})
watchEffect(async onInvalidate=>{
  const v = v3.value
  // 存在异步
  const timeout = setTimeout(()=>{
    console.log(v,'timeout')
  },1000);
  onInvalidate(()=>{
    clearTimeout(timeout)
  })
})

重复执行会触发 onInvalidate,取消上一次的异步请求

停止监听
const stop = watchEffect(() => {
  console.log("name:", demo.item.num);
});

const stopWatchEffect = () => {
  console.log("停止监听");
  stop();
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

anjushi_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值