watch监听及实时翻译实例
watch监听及实时翻译实例
watch的作用:
Vue 中 watch 监听器的核心作用是监听 Vue 实例中 data/computed 里的响应式数据,当数据发生变化时,自动执行你预先定义的回调函数,简单说就是 「数据变,代码跑」,是 Vue 实现**数据变化驱动业务逻辑执行 ** 的核心方式之一。
watch的三种用法:
Vue 中 watch 监听器的基本语法可以分为基础写法、监听嵌套数据、高级配置三类,结合你的代码场景,我用简洁的结构和案例说明,看完就能直接用。
一、基础语法:监听根级响应式数据
监听 data 中直接定义的响应式数据(比如 data 里的 words: ''),语法是「数据名:回调函数」。
new Vue({
data: {
数据名: 初始值
},
watch: {
// 监听“数据名”的变化
数据名(newValue, oldValue) {
// newValue:变化后的新值
// oldValue:变化前的旧值(可选)
// 数据变化后执行的逻辑
}
}
})
二、监听嵌套数据:对象 / 数组中的属性
如果数据是嵌套在对象 / 数组中(比如你的 obj.words),需要用字符串形式写嵌套路径。
new Vue({
data: {
父对象: {
子属性: 初始值
}
},
watch: {
// 用字符串写“父对象.子属性”
'父对象.子属性'(newValue, oldValue) {
// 数据变化后执行的逻辑
}
}
})
三、高级配置:深度监听 / 立即执行
如果需要监听对象所有属性的变化(深度监听),或初始化时立即执行一次回调,可以用对象形式配置 watch。
watch: {
监听的数据: {
handler(newValue, oldValue) {
// 数据变化后执行的逻辑(核心回调,替代之前的函数)
},
deep: true, // 可选:是否深度监听(对象所有属性变化都触发)
immediate: true // 可选:是否初始化时立即执行一次回调
}
}
四、总结:3 种常用写法对比
| 写法类型 | 适用场景 | 语法示例 |
|---|---|---|
| 基础函数式 | 监听根级数据 | words(newVal) { ... } |
| 字符串路径式 | 监听嵌套数据(对象 / 数组子属性) | 'obj.words'(newVal) { ... } |
| 对象配置式 | 深度监听 / 立即执行 | user: { handler() {}, deep: true } |
五.示例的运行顺序
Document
翻译成的语言:
文档翻译
{{ result }}
以下分两个场景解读:
场景 1:单字符输入(输入后 300ms 内无再输入,触发翻译)
比如只输入一个字苹,全程无后续输入,完整执行顺序(共 8 步):
初始状态
obj.words = ''、timer = ''、result = '',无任何延时器。
执行步骤
- 文本框输入
苹,obj.words从''变为'苹',触发 watch 监听obj.words,进入监听方法; - 执行
clearTimeout(this.timer):此时timer是初始空字符串,清空操作无实际效果(没有可清空的延时器); - 执行
this.timer = setTimeout(...):创建新的延时器,分配一个唯一数字 ID(比如123),并把这个 ID 赋值给this.timer(此时timer = 123); - 延时器开始倒计时 300ms,这期间页面无其他操作;
- 300ms 倒计时结束,执行 setTimeout 内部的异步回调函数;
- 执行
await axios(...):携带参数words: '苹',向翻译接口发送 GET 请求; - 接口返回数据,执行
this.result = res.data.data:把翻译结果赋值给result,页面上的{{ result }}自动更新,显示翻译内容; - 执行
console.log(res.data.data):控制台打印翻译结果,一轮监听执行完毕。
场景 2:连续输入(防抖核心,多次触发监听,仅最后一次生效)
这是防抖的实际使用场景(比如快速输入苹→苹果,两次输入间隔<300ms),完整执行顺序(共 13 步),核心是「后一次输入清空前一次的延时器,仅保留最后一次的延时器执行」:
初始状态
obj.words = ''、timer = ''、result = '',无任何延时器。
执行步骤
第一次输入苹(触发第一次监听)
- 输入
苹,obj.words变为'苹',触发第一次 watch 监听,进入监听方法; - 执行
clearTimeout(this.timer):timer为空,无实际效果; - 执行
this.timer = setTimeout(...):创建延时器,赋值 ID123(此时timer = 123); - 延时器开始倒计时 300ms(此时倒计时剩余约 200ms,还没到时间);
快速输入果(触发第二次监听,间隔<300ms,核心防抖)
- 输入
果,obj.words变为'苹果',触发第二次 watch 监听,再次进入监听方法; - 执行
clearTimeout(this.timer):清空 ID 为 123 的延时器(第一次创建的延时器还没执行,直接被取消),此时timer = 123但延时器已失效; - 执行
this.timer = setTimeout(...):创建新的延时器,分配新 ID456,并赋值给this.timer(此时timer = 456,覆盖旧 ID); - 新的延时器重新开始倒计时 300ms,这期间无其他输入;
最后一次延时器执行(仅这次触发翻译)
- 300ms 倒计时结束,执行第二次创建的延时器内部回调;
- 执行
await axios(...):携带参数words: '苹果',发送 GET 请求; - 接口返回数据,执行
this.result = res.data.data:页面更新最终的翻译结果; - 执行
console.log(res.data.data):控制台打印最终翻译结果; - 两轮监听执行完毕,
timer仍为456(后续无输入则无需处理,若再有输入会继续清空)。
核心总结(timer 执行的 3 个关键规律)
- 每次输入必清空:只要
obj.words变化,进入 watch 后第一步必执行clearTimeout(this.timer),目的是取消上一次未执行的延时器; - 每次输入必新建:清空后会立即创建新的延时器,并用
this.timer存储最新的延时器 ID,覆盖旧 ID; - 仅最后一次生效:连续输入时,前几次的延时器都会被后一次的
clearTimeout清空,只有最后一次输入创建的延时器,能完成 300ms 倒计时并执行接口请求,这就是防抖的核心作用(避免输入过程中频繁发请求,减轻接口压力)。
简单说:timer 的执行逻辑就是 「清旧的 → 建新的 → 等延时 → 执行最后一个」。







