温故而知新(03)------ watch vs watcheffect

前言

由于之前一直使用watch,不怎么使用watchEffect,今天就来简单的看下两者的不同之处

watch

先从简单的代码的使用方法看起:

xml 复制代码
<script setup>
import {watch, ref, reactive, computed} from "vue";

const name = ref('小红');

setTimeout(() => {
  name.value = '小白'
}, 2000)
watch(name, (newval, oldval) => {
  console.log(newval, oldval)
}, {
  deep: false,
  immediate: false
})
</script>
<template>
  <div>
    123456.吐槽,你不说我怎么知道啊
  </div>
</template>

watcht简单的监听只需要三个参数:

1.监听的对象 2.监听后的回调函数,第一个值是新值,第二个值是老值 3.监听时的触发选项,是否深度监听和是否立即监听

监听对象中的某个key:

1.方便的做法是在选项中使用深度监听,配置:{deep:true}这样就可以监听到整个对象是发生了变化的。

2.直接监听对象的某个值,这样还能节约性能。

代码演示如下:

xml 复制代码
<script setup>
import {watch, ref, reactive, computed} from "vue";
const TestObj = ref({
 name:'小红娘',
 age:18,
})

watch(TestObj.value.name,(newval,oldval)=>{
 console.log(newval,oldval)
})
setTimeout(() => {
 TestObj.value.name = '小白'
 console.log(11)
}, 2000)
</script>
<template>
 <div>
   123456.吐槽,你不说我怎么知道啊
 </div>
</template>

运行效果如下,并未打印新旧值

这样的方式不允许我们在vue3中使用,我们在监听某个对象的值时,需要用getter方法导出。

完整代码如下:

xml 复制代码
<script setup>
import {watch, ref, reactive, computed} from "vue";
const TestObj = ref({
  name:'小红娘',
  age:18,
})

watch(() => TestObj.value.name,(newval,oldval)=>{
  console.log(newval,oldval)
})
setTimeout(() => {
  TestObj.value.name = '小白'
  console.log(11)
}, 2000)
</script>
<template>
  <div>
    123456.吐槽,你不说我怎么知道啊
  </div>
</template>

运行结果如下:

watchEffect

watchEffect,它立即执行传入的一个函数,同时响应式追踪其依赖,并在其依赖变更时重新运行该函数。 也就是说,wactheffect会自动收集函数中的响应式依赖,并且初始化运行一次该函数(相当于watch开启了immediate:true)

举例代码如下:

xml 复制代码
<script setup>
// import {watch, ref, reactive, computed} from "vue";
// const TestObj = ref({
//   name:'小红娘',
//   age:18,
// })
//
// watch(() => TestObj.value.name,(newval,oldval)=>{
//   console.log(newval,oldval)
// })
// setTimeout(() => {
//   TestObj.value.name = '小白'
//   console.log(11)
// }, 2000)

import { ref, reactive, watch, watchEffect } from 'vue';
const single = reactive({ count: 1, test: { a: 1, b: 2 } });
const handleClick = function () {
  single.test.a++;
};
watchEffect(() => {
  console.log('-----', single.test.a);
});

</script>
<template>
  <div>
    <button @click="handleClick">点击</button>
  </div>
</template>

代码初始化运行如下:

当我们点击时如下:

值得注意的是,watcheffect只能获取到最新的值(在函数中直接访问),而不像watch那样可以拿到新值和旧值。

注意:watchEffect在监听数据时,同步函数发生变化时只触发一次监听

代码如下:

xml 复制代码
<template>
  <div class="mine-box">
    <div ref="countDom">{{ single.test.a }}</div>
    <button @click="handleClick">按钮</button>
  </div>
</template>

<script setup>
import { ref, reactive, watch, watchEffect } from 'vue';
const single = reactive({ count: 1, test: { a: 1, b: 2 } });
const countDom = ref(null);
const handleClick = function () {
  single.test.a++;
};
watchEffect(() => {
  console.log(countDom.value);
  console.log('-----', single.test.a);
});
</script>

<style>
.mine-box {
  text-align: center;
}
</style>

当我们点击按钮时,运行效果如下:

可以看到函数只是运行了一次。

watcheffect入参: onInvalidate

onInvalidate在值即将发生改变时发生一次调用

代码如下:

xml 复制代码
<script setup>
import {  reactive,  watchEffect } from 'vue';
const single = reactive({ count: 1, test: { a: 1, b: 2 } });
const handleClick = function () {
  single.test.a++;
};
const stop = watchEffect(onInvalidate => {
  console.log('--监听执行---', single.test.a);
  if (single.test.a > 5) {
    stop();
  }
  onInvalidate(()=>{
    console.log("看好了,我是在属性值发生改变前而触发的")
  })
});

</script>
<style>
.mine-box {
  text-align: center;
}
</style>
<template>
  <div class="mine-box">
    123456
    <button @click="handleClick">按钮</button>
  </div>
</template>

初始化如下:

当我们在点击 按钮时发生如下变化:

销毁监听

watchEffect所在的组件被卸载时 会隐式调用stop函数停止侦听。

通过显示调用返回值停止侦听

ini 复制代码
const stop = watchEffect(onInvalidate => {
  console.log('--监听执行---', single.test.a);
  if (single.test.a > 5) {
    stop();
  }
});
scss 复制代码
const name = ref('小红')

const stop = watch(name, ()=>{
  console.log(name.value)
});

setTimeout(()=>{
  stop()
},1000)
setTimeout(()=>{
  name.value = '111'
  console.log(name)
},2000)

总结:

watchwatchEffect 的主要功能是相同的,都能响应式地执行回调函数。

依赖收集 执行时机 监听对象 返回值
watcheffect 初始化时就收集,并立即执行回调函数 可以没有具体的监听对象 可以没有返回值
watch 初始化时收集,默认当依赖有变更才执行回调函数 必须要有具体的监听对象 有返回值(新值和旧值)
computed 初始化时收集,默认当依赖有变更才执行回调函数 需要具体的对象 返回的是计算属性值(必须有返回)
相关推荐
陈随易1 分钟前
VSCode v1.102发布,AI体验大幅提升
前端·后端·程序员
ma776 分钟前
JavaScript 获取短链接原始地址的解决方案
前端
该用户已不存在6 分钟前
关于我把Mac Mini托管到机房,后续来了,还有更多玩法
服务器·前端·mac
tianchang9 分钟前
SSR 深度解析:从原理到实践的完整指南
前端·vue.js·设计模式
闲蛋小超人笑嘻嘻10 分钟前
前端面试十一之TS
前端
摆烂为不摆烂10 分钟前
😁深入JS(四): 一文让你完全了解Iterator+Generator 实现async await
前端
DoraBigHead23 分钟前
🧠 别急着传!大文件上传里,藏着 Promise 的高级用法
前端·javascript·面试
嘉琪00126 分钟前
封装一个有最小化的dialog组件
前端·javascript·css
水果里面有苹果28 分钟前
20-C#构造函数--虚方法
java·前端·c#
Zachery Pole28 分钟前
BootStrap
前端·bootstrap·html