温故而知新(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 初始化时收集,默认当依赖有变更才执行回调函数 需要具体的对象 返回的是计算属性值(必须有返回)
相关推荐
以对_14 分钟前
uview表单校验不生效问题
前端·uni-app
程序猿小D1 小时前
第二百六十七节 JPA教程 - JPA查询AND条件示例
java·开发语言·前端·数据库·windows·python·jpa
奔跑吧邓邓子2 小时前
npm包管理深度探索:从基础到进阶全面教程!
前端·npm·node.js
前端李易安2 小时前
ajax的原理,使用场景以及如何实现
前端·ajax·okhttp
汪子熙3 小时前
Angular 服务器端应用 ng-state tag 的作用介绍
前端·javascript·angular.js
Envyᥫᩣ3 小时前
《ASP.NET Web Forms 实现视频点赞功能的完整示例》
前端·asp.net·音视频·视频点赞
Мартин.7 小时前
[Meachines] [Easy] Sea WonderCMS-XSS-RCE+System Monitor 命令注入
前端·xss
昨天;明天。今天。8 小时前
案例-表白墙简单实现
前端·javascript·css
数云界8 小时前
如何在 DAX 中计算多个周期的移动平均线
java·服务器·前端
风清扬_jd8 小时前
Chromium 如何定义一个chrome.settingsPrivate接口给前端调用c++
前端·c++·chrome