Vue中的watch笔记

本文介绍了Vue中watch的基本概念和用法,包括简单的监听、immediate和deep选项。通过实例展示了如何监听属性变化,当属性值更新时,对应的回调函数会被调用,展示新旧值的变化。此外,探讨了immediate选项如何使得回调在初始渲染时立即执行,以及deep选项用于深度监听对象属性的变化。

Watch的简单理解

引用官方解释就是:一个对象,键是需要观察的表达式,值是对应回调函数。值也可以是方法名,或者包含选项的对象。Vue 实例将会在实例化时调用 w a t c h ( ) , 遍 历 w a t c h 对 象 的 每 一 个 p r o p e r t y 。 语 法 : v m . watch(),遍历 watch 对象的每一个 property。 语法:vm. watch()watchpropertyvm.watch( expOrFn, callback, [options] )
参数:

  • {string | Function} expOrFn
  • {Function | Object} callback
  • {Object} [options]

{boolean} deep
{boolean} immediate

返回值:{Function} unwatch
这些都是一些官方给我们的解释跟一些用法
现在我们来简单看一下代码怎么实现

简单的监听

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<script src="./base/vue.js"></script>
<body>
        <div id="app">
            <input type="text" v-model="num">
        </div>
</body>
<script>
        new Vue({
        el: '#app',
        data: {
            num: ''
        },
        watch: {
            num(newVal, oldVal) {
                console.log('oldVal:',oldVal)
                console.log('newVal:',newVal)
            }
        }
    })
 
</script>
</html>

我们进行监听num属性的数据变化
只要num值发生改变那么num方法就会被触发
方法中第一个参数的值是新的值也就是更改变化后的值
第二个则是旧值,之前的值
当我在输入框中打印一个2
在这里插入图片描述
会出现旧值为空,新值为2
再输入框中再加一个3,则
在这里插入图片描述
会打印出旧值为2,新值为23

immediate

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<script src="./base/vue.js"></script>
<body>
        <div id="app">
            <input type="text" v-model="num">
        </div>
</body>
<script>
        new Vue({
        el: '#app',
        data: {
            num: 1
        },
        watch: {
            num: {
            	// 立即处理 进入页面就触发
                immediate: true,
                // 数据发生变化就会调用这个函数 
                handler(newVal, oldVal) {
                    console.log('oldVal:', oldVal)
                    console.log('newVal:', newVal)
                }
            }
        }

    })
 
</script>
</html>

immediate字面意思就是马上, immediate: true,就是页面加载立马执行
在这里插入图片描述
由于旧值是没有所以打印undefined

deep

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<script src="./base/vue.js"></script>
<body>
    <div id="app">
        <input type="button" value="更改名字" @click="change">
    </div>
</body>
<script>
   new Vue({
        el: '#app',
        data: {
            food: {
                id: 1,
                name: '冰激凌'
            }
        },
        methods: {
            change() {
                this.food.name = '棒棒糖'
            }
        },
        watch: {
        	// 第一种方式:监听整个对象,每个属性值的变化都会执行handler
        	// 注意:属性值发生变化后,handler执行后获取的 newVal 值和 oldVal 值是一样的
            food: {
                // 每个属性值发生变化就会调用这个函数
                handler(newVal, oldVal) {
                    console.log('oldVal:', oldVal)
                    console.log('newVal:', newVal)
                },
                // 立即处理 进入页面就触发
                immediate: true,
                // 深度监听 属性的变化
                deep: true
            },
            // 第二种方式:监听对象的某个属性,被监听的属性值发生变化就会执行函数
            // 函数执行后,获取的 newVal 值和 oldVal 值不一样
            'food.name'(newVal, oldVal) {
                console.log('oldVal:', oldVal)   // 冰激凌
                console.log('newVal:', newVal)   // 棒棒糖
            }
        }
    })

 
</script>
</html>

刚开始打印
在这里插入图片描述
点击之后打印
在这里插入图片描述
这部分引用了一些别人的例子

想要了解更多点击vue.watch

Vue 3 中,使用 `watch` 监听 **对象**(尤其是通过 `reactive` 或 `ref` 创建的响应式对象)时,需要注意语法和配置,否则可能无法正确触发监听。 --- ### ✅ 正确方式:监听 `reactive` 定义的对象 ```vue <script setup> import { reactive, watch } from 'vue' const user = reactive({ name: 'Alice', profile: { age: 25, city: 'Beijing' } }) // ❌ 错误写法:直接传入 reactive 对象(不会深度追踪内部变化) // watch(user, (newVal, oldVal) => { ... }) // ✅ 正确写法1:使用 getter 函数返回要监听的属性 watch( () => user.name, (newName, oldName) => { console.log(`name 变化: ${oldName} → ${newName}`) } ) // ✅ 正确写法2:监听嵌套属性 watch( () => user.profile.age, (newAge, oldAge) => { console.log(`age 变化: ${oldAge} → ${newAge}`) } ) // ✅ 正确写法3:监听整个对象的所有深层变化 —— 使用 deep: true watch( () => ({ ...user }), // 或者直接用一个函数返回 user 的结构 (newUser, oldUser) => { console.log('user 发生深度变化', newUser) }, { deep: true } ) // ✅ 更推荐的方式:直接监听整个 reactive 对象的变化(Vue 3 支持) watch( user, // 可以直接传入 reactive 对象 (newVal, oldVal) => { console.log('user 被修改', newVal) }, { deep: true } // 必须加 deep 才能监听到内部嵌套属性变化 ) </script> <template> <div> <p>{{ user.name }} - {{ user.profile.age }}岁</p> <button @click="user.name = 'Bob'">改名字</button> <button @click="user.profile.age++">年龄+1</button> <button @click="user.profile.city = 'Shanghai'">改城市</button> </div> </template> ``` --- ### ✅ 监听 `ref` 包裹的对象 ```js import { ref, watch } from 'vue' const user = ref({ name: 'Alice', age: 25 }) // 监听 ref 对象的某个属性 watch( () => user.value.name, (newName) => { console.log('名字变了:', newName) } ) // 监听整个 ref 对象(需要 deep) watch( user, (newUser, oldUser) => { console.log('user 更新了', newUser) }, { deep: true } ) ``` --- ### 🔍 关键点解释 | 写法 | 是否有效 | 说明 | |------|---------|------| | `watch(user, cb)` | ✅ 有效(仅限 reactive) | Vue 3 允许直接监听 `reactive` 对象,但需 `deep: true` 才能感知深层变化 | | `watch(() => user.xxx, cb)` | ✅ 推荐 | 精确监听某个字段,性能更好 | | `watch(user, cb, { deep: true })` | ✅ 必须用于深层监听 | 否则只监听引用变化,不监听内部属性 | | `watch(user, cb, { immediate: true })` | ✅ 首次立即执行 | 常用于初始化副作用 | --- ### ⚠️ 常见错误 #### ❌ 错误1:监听 `reactive` 对象却不加 `deep` ```js watch(user, (newVal) => { console.log(newVal) }) // 修改 user.profile.age 不会触发!因为不是引用变化 ``` #### ❌ 错误2:试图监听 `reactive` 的根引用变化 ```js watch(user, ...) // 如果你重新赋值 user = {},这是无效的,因为 reactive 不能被重新赋值 ``` > 💡 提示:`reactive` 返回的是一个代理对象,你不能像 `ref` 一样替换它。如需替换整个对象,请使用 `ref`。 --- ### ✅ 替代方案:使用 `ref` 包装对象(更适合替换场景) ```js const user = ref({ name: 'Alice' }) watch(user, (newVal) => { console.log('user 被替换为新对象') }, { deep: true }) // 可以重新赋值 setTimeout(() => { user.value = { name: 'Bob' } // 触发 watch }, 1000) ``` --- ### 🧩 实际应用场景 #### 场景:表单数据变化时自动保存 ```js const form = reactive({ username: '', email: '' }) watch( form, (newForm) => { console.log('表单变化,准备自动保存...', newForm) // debounce 后提交 API }, { deep: true } ) ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值