程序员scholar 程序员scholar
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • Web 标准

    • HTML
    • CSS
    • JavaScript
  • 前端框架

    • Vue2
    • Vue3
    • Vue3 + TS
    • 微信小程序
    • uni-app
  • 工具与库

    • jQuery
    • Ajax
    • Axios
    • Webpack
    • Vuex
    • WebSocket
    • 第三方登录
  • 后端与语言扩展

    • ES6
    • Typescript
    • node.js
  • Element-UI
  • Apache ECharts
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • Web 标准

    • HTML
    • CSS
    • JavaScript
  • 前端框架

    • Vue2
    • Vue3
    • Vue3 + TS
    • 微信小程序
    • uni-app
  • 工具与库

    • jQuery
    • Ajax
    • Axios
    • Webpack
    • Vuex
    • WebSocket
    • 第三方登录
  • 后端与语言扩展

    • ES6
    • Typescript
    • node.js
  • Element-UI
  • Apache ECharts
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
npm

(进入注册为作者充电)

  • Vue2

  • Vue3

    • 初识Vue3
    • 组合式API
    • Vue3中的data数据
    • vue3 的 script标签
    • setup函数中执行顺序
    • toRefs() 与 toRef()
    • computed()
    • Vue3弱化this
    • watch() 和 watchEffec()
      • 一、watch的使用
        • 1. watch 的作用
        • 2. 特点
        • 3. 语法格式
        • 4. 常见使用场景
        • 4.1 监听 ref 的基本类型数据
        • 4.2 监听 ref 的对象类型数据
        • 4.3 监听 reactive 的对象类型数据
        • 4.4 监听特定属性
        • 4.5 监听多个数据
        • 4.6 监听 getter 函数
        • 4.7 监听回调函数的返回值
        • 5. 特殊场景使用
        • 5.1 监听路由变化
        • 5.2 监听 props 数据
        • 5.3 监听 Vuex 的数据
        • 5.4 监听异步数据加载完成
        • 6. 使用注意事项
        • 7. 使用小结
        • 7.1 不涉及嵌套属性:可以直接监听
        • 7.2 涉及嵌套属性:必须使用回调函数
      • 二、watchEffect的使用
        • 1. watchEffect 语法
        • 2. 使用 watchEffect
    • define函数用法
    • defineExpose() 和 ref 属性
    • vue.config.js
    • 生命周期
    • Vue3全局API调用
    • 自定义 Hook
    • 传递数据(props)
    • 路由
    • pinia
    • 组件通信
    • getCurrentInstance() 和 nextTick()
    • Vue3 新组件
  • vue3 + TS 项目集成

  • Vue全家桶
  • Vue3
scholar
2024-08-05
目录

watch() 和 watchEffec()

# watch() 和 watchEffec()

# 一、watch的使用

# 1. watch 的作用

watch 是 Vue 3 中用于监听数据变化的工具。与 Vue 2 的 watch 功能一致,watch 允许我们监控数据变化并执行对应的逻辑。

# 2. 特点

  • Vue 3 中的 watch 可以监听以下四种数据:
    1. 使用 ref 定义的数据。
    2. 使用 reactive 定义的数据。
    3. 函数返回的值(getter 函数)。
    4. 包含上述内容的数组。
  • 当被监听的数据发生变化时,Vue 会自动调用回调函数,newValue 和 oldValue 作为参数传递到回调函数中。

# 3. 语法格式

watch(source, callback, options?)
1
  • source:被监听的数据,可以是 ref、reactive、getter 函数或包含上述内容的数组。
  • callback:回调函数,数据发生变化时执行,接收两个参数:newValue 和 oldValue。
  • options:可选参数对象:
    • deep:是否开启深度监听,默认为 false。
    • immediate:是否在初始挂载时立即执行回调,默认为 false。

**即时回调** (`immediate: true`)

  • 当你用 watch 监听数据时,默认情况下,只有当监听的数据发生变化时,回调函数才会被触发。
  • 如果加上 immediate: true,watch 会 在刚开始时就立刻执行一次,即使数据没有变化。

# 4. 常见使用场景

# 4.1 监听 ref 的基本类型数据

监听 ref 定义的基本类型数据:

let count = ref(0);

watch(count, (newValue, oldValue) => {
  console.log('count 变化了', newValue, oldValue);
});
1
2
3
4
5

# 4.2 监听 ref 的对象类型数据

监听 ref 定义的对象类型数据时:

  • 默认监听的是对象的地址值变化。
  • 需要手动开启 deep: true 来监听对象内部属性变化。
let person = ref({ name: '张三', age: 18 });

watch(person, (newValue, oldValue) => {
  console.log('person 变化了', newValue, oldValue);
}, { deep: true });
1
2
3
4
5

# 4.3 监听 reactive 的对象类型数据

监听 reactive 定义的对象时:

  • 默认开启深度监听。
  • reactive 对象的地址值不会改变,因此监听到的 newValue 和 oldValue 通常是相同的对象。
let person = reactive({ name: '张三', age: 18 });

watch(person, (newValue, oldValue) => {
  console.log('person 变化了', newValue, oldValue);
});
1
2
3
4
5

# 4.4 监听特定属性

监听 reactive 或 ref 对象中的特定属性:

// 监听基本类型属性
watch(() => person.name, (newValue, oldValue) => {
  console.log('person.name 变化了', newValue, oldValue);
});

// 监听对象类型属性
watch(() => person.car, (newValue, oldValue) => {
  console.log('person.car 变化了', newValue, oldValue);
}, { deep: true });
1
2
3
4
5
6
7
8
9

# 4.5 监听多个数据

可以通过数组监听多个数据:

watch([() => person.name, person.age], (newValues, oldValues) => {
  console.log('person.name 或 person.age 变化了', newValues, oldValues);
});
1
2
3

# 4.6 监听 getter 函数

watch 可以监听一个 getter 函数返回的值。当该函数的返回值变化时,会触发回调函数:

let person = reactive({ name: '张三', age: 18 });

watch(() => person.age > 18, (newValue, oldValue) => {
  console.log('是否成年发生了变化', newValue, oldValue);
});
1
2
3
4
5

# 4.7 监听回调函数的返回值

# 5. 特殊场景使用

# 5.1 监听路由变化

监听 Vue Router 的路由变化:

import { useRoute } from 'vue-router';

const route = useRoute();

watch(() => route.path, (newPath, oldPath) => {
  console.log('路由变化了', newPath, oldPath);
});
1
2
3
4
5
6
7

# 5.2 监听 props 数据

监听子组件的 props 数据:

props: {
  user: {
    type: Object,
    required: true
  }
},

setup(props) {
  watch(() => props.user, (newValue, oldValue) => {
    console.log('props.user 变化了', newValue, oldValue);
  }, { deep: true });
}
1
2
3
4
5
6
7
8
9
10
11
12

# 5.3 监听 Vuex 的数据

通过 watch 监听 Vuex 状态的变化:

import { useStore } from 'vuex';

const store = useStore();

watch(() => store.state.count, (newValue, oldValue) => {
  console.log('Vuex state.count 变化了', newValue, oldValue);
});
1
2
3
4
5
6
7

# 5.4 监听异步数据加载完成

在异步数据加载时使用 watch 监听其状态:

let dataLoaded = ref(false);

watch(dataLoaded, (newValue) => {
  if (newValue) {
    console.log('数据加载完成');
  }
});

// 模拟数据加载
setTimeout(() => {
  dataLoaded.value = true;
}, 2000);
1
2
3
4
5
6
7
8
9
10
11
12

# 6. 使用注意事项

  • 深度监听:当需要监听对象内部属性时,需手动开启 deep: true。
  • 即时回调:当需要在初始阶段触发回调时,使用 immediate: true。
  • 性能优化:避免对大型数据对象开启深度监听,可能影响性能。
  • 停止监听:可以通过调用 watch 返回的停止函数来手动停止监听。
const stopWatch = watch(count, (newValue, oldValue) => {
  console.log('count 变化了', newValue, oldValue);
});

stopWatch(); // 停止监听
1
2
3
4
5

# 7. 使用小结

# 7.1 不涉及嵌套属性:可以直接监听

如果监听的是 ref 或 reactive 定义的顶层属性,可以直接传入 ref 或 reactive 数据作为 watch 的第一个参数,而无需使用回调函数。例如:

let count = ref(0);

// 直接监听
watch(count, (newValue, oldValue) => {
  console.log('count 变化了', newValue, oldValue);
});

// 使用回调函数监听
watch(() => count.value, (newValue, oldValue) => {
  console.log('count 变化了', newValue, oldValue);
});
1
2
3
4
5
6
7
8
9
10
11

# 7.2 涉及嵌套属性:必须使用回调函数

如果监听的是嵌套属性(无论是 ref 还是 reactive 定义的对象内部的属性),需要通过回调函数显式访问嵌套属性,以确保 Vue 捕获依赖关系。例如:

监听 reactive 对象的嵌套属性

let person = reactive({ name: '张三', details: { age: 18 } });

// 必须使用回调函数监听嵌套属性
watch(() => person.details.age, (newValue, oldValue) => {
  console.log('person.details.age 变化了', newValue, oldValue);
});
1
2
3
4
5
6

监听 props 或 store 的嵌套属性

// props 数据
watch(() => props.user.name, (newValue, oldValue) => {
  console.log('props.user.name 变化了', newValue, oldValue);
});

// Vuex 数据
watch(() => store.state.user.details.age, (newValue, oldValue) => {
  console.log('store.state.user.details.age 变化了', newValue, oldValue);
});
1
2
3
4
5
6
7
8
9

总结

  • 顶层属性: 直接监听即可,无需回调函数。
  • 嵌套属性: 必须通过回调函数监听,以确保 Vue 能正确追踪属性的依赖。
  • 推荐习惯: 对于复杂场景,使用回调函数监听属性可以避免遗漏依赖,是一种更安全的方式。

# 二、watchEffect的使用

作用:watchEffect 用于立即运行一个函数,同时响应式地追踪其依赖,并在依赖更改时重新执行该函数。

watch 对比 watchEffect

  1. 都能监听响应式数据的变化,不同的是监听数据变化的方式不同。
  2. watch:需要明确指出监视的数据。
  3. watchEffect:不用明确指出监视的数据(函数中用到哪些属性,那就监视哪些属性)。

# 1. watchEffect 语法




 


 







import { ref, watchEffect } from 'vue';

// 定义响应式数据
let temp = ref(0);
let height = ref(0);

// 使用 watchEffect 监听数据变化
const stopWatch = watchEffect(() => {
  // 函数内部用到的响应式数据 temp 和 height 被自动追踪
  if (temp.value >= 50 || height.value >= 20) {
    console.log('联系服务器');
  }
});
1
2
3
4
5
6
7
8
9
10
11
12
13
  • effect: 一个函数,watchEffect 会立即运行这个函数,并响应式地追踪其依赖。在依赖变化时,会重新执行该函数。

可选的 onCleanup 函数

在 watchEffect 函数内部,可以调用 onCleanup 注册清理回调,该回调在副作用重新运行前或停止跟踪时调用。














 
 
 
 


import { ref, watchEffect } from 'vue';

// 定义响应式数据
let temp = ref(0);
let height = ref(0);

// 使用 watchEffect 监听数据变化
const stopWatch = watchEffect((onCleanup) => {
  // 函数内部用到的响应式数据 temp 和 height 被自动追踪
  if (temp.value >= 50 || height.value >= 20) {
    console.log('联系服务器');
  }

  // 注册一个清理回调,在副作用重新运行前或停止跟踪时调用
  onCleanup(() => {
    console.log('清理副作用');
  });
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 2. 使用 watchEffect














 



 







 







 




 







<template>
  <div class="person">
    <h1>需求:水温达到50℃,或水位达到20cm,则联系服务器</h1>
    <h2 id="demo">水温:{{ temp }}</h2>
    <h2>水位:{{ height }}</h2>
    <button @click="changeTemp">水温 +10</button>
    <button @click="changeHeight">水位 +1</button>
  </div>
</template>

<script lang="ts" setup>
import { ref, watchEffect } from 'vue';

// 定义响应式数据
let temp = ref(0);
let height = ref(0);

// 方法:改变 temp 和 height 的值
function changeTemp() {
  temp.value += 10;
}
function changeHeight() {
  height.value += 1;
}

// 使用 watchEffect 监听数据变化,不用明确指出监视的数据
const stopWatch = watchEffect((onCleanup) => {
  // 函数内部用到的响应式数据 temp 和 height 被自动追踪
  if (temp.value >= 50 || height.value >= 20) {
    console.log(document.getElementById('demo')?.innerText);
    console.log('联系服务器');
  }

  // 注册一个清理回调,在副作用重新运行前或停止跟踪时调用
  onCleanup(() => {
    console.log('清理副作用');
  });

  // 如果水温达到 100℃,或水位达到 50cm,取消监视
  if (temp.value === 100 || height.value === 50) {
    console.log('清理了');
    stopWatch(); // 停止监听
  }
});
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

总结

  • watchEffect 用于立即运行一个函数,并响应式地追踪其依赖。在依赖更改时重新执行该函数。
  • 不需要明确指出要监视的数据,函数内部用到的响应式数据会被自动追踪。
  • 可以注册清理回调 onCleanup,在副作用重新运行前或停止跟踪时调用。
编辑此页 (opens new window)
上次更新: 2025/01/30, 23:55:43
Vue3弱化this
define函数用法

← Vue3弱化this define函数用法→

Theme by Vdoing | Copyright © 2019-2025 程序员scholar
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式