在 JavaScript 中有几种方法可以监听变量的变化。我列举几种常用的方法:
使用 Vue 的 watch(如果在 Vue 项目中):
new Vue({ data: { someValue: '' }, watch: { // 基础监听 someValue(newVal, oldVal) { console.log('值变化:', oldVal, '->', newVal); }, // 深度监听对象 someObject: { handler(newVal, oldVal) { console.log('对象变化:', oldVal, '->', newVal); }, deep: true }, // 立即执行 someData: { handler(newVal, oldVal) { console.log('数据变化:', oldVal, '->', newVal); }, immediate: true } } });
使用 Object.defineProperty(Vue2 的实现原理):
let value = ''; let oldValue = value; Object.defineProperty(window, 'watchedValue', { get() { return value; }, set(newValue) { oldValue = value; value = newValue; // 值变化时的回调 onValueChange(value, oldValue); } }); function onValueChange(newValue, oldValue) { console.log('值变化:', oldValue, '->', newValue); } // 使用 watchedValue = 'new value'; // 会触发 onValueChange
使用 Proxy(Vue3 的实现原理):
const data = { value: '' }; const proxy = new Proxy(data, { get(target, property) { return target[property]; }, set(target, property, value) { const oldValue = target[property]; target[property] = value; // 值变化时的回调 onValueChange(property, value, oldValue); return true; } }); function onValueChange(property, newValue, oldValue) { console.log(`${property} 变化:`, oldValue, '->', newValue); } // 使用 proxy.value = 'new value'; // 会触发 onValueChange
使用 MutationObserver(监听 DOM 变化):
// 监听 DOM 元素属性或内容变化 const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { console.log('DOM变化:', mutation); }); }); // 配置观察选项 const config = { attributes: true, // 监听属性变化 childList: true, // 监听子节点变化 characterData: true, // 监听文本内容变化 subtree: true // 监听所有后代节点 }; // 开始观察 const targetNode = document.getElementById('someElement'); observer.observe(targetNode, config); // 停止观察 // observer.disconnect();
创建自定义可观察对象(Observable):
class Observable { constructor(value) { this._value = value; this._listeners = []; } get value() { return this._value; } set value(newValue) { const oldValue = this._value; this._value = newValue; this._notify(newValue, oldValue); } subscribe(listener) { this._listeners.push(listener); // 返回取消订阅函数 return () => { this._listeners = this._listeners.filter(l => l !== listener); }; } _notify(newValue, oldValue) { this._listeners.forEach(listener => listener(newValue, oldValue)); } } // 使用示例 const counter = new Observable(0); // 添加监听器 const unsubscribe = counter.subscribe((newVal, oldVal) => { console.log('计数变化:', oldVal, '->', newVal); }); // 修改值 counter.value = 1; // 会触发监听器 // 取消订阅 unsubscribe();
使用 EventEmitter 模式:
class EventEmitter { constructor() { this._events = {}; } on(event, callback) { if (!this._events[event]) { this._events[event] = []; } this._events[event].push(callback); return () => this.off(event, callback); } off(event, callback) { if (!this._events[event]) return; this._events[event] = this._events[event].filter(cb => cb !== callback); } emit(event, ...args) { if (!this._events[event]) return; this._events[event].forEach(callback => callback(...args)); } } // 使用示例 class WatchableValue extends EventEmitter { constructor(initialValue) { super(); this._value = initialValue; } get value() { return this._value; } set value(newValue) { const oldValue = this._value; this._value = newValue; this.emit('change', newValue, oldValue); } } // 使用 const watchable = new WatchableValue(0); // 添加监听器 const unsubscribe = watchable.on('change', (newVal, oldVal) => { console.log('值变化:', oldVal, '->', newVal); }); // 修改值 watchable.value = 1; // 会触发监听器 // 取消监听 unsubscribe();
选择建议:
在 Vue 项目中,优先使用 watch
需要深度监听对象变化时,使用 Proxy监听
DOM 变化时,使用 MutationObserver
简单场景可以使用 Object.defineProperty
需要更复杂的订阅/发布机制时,可以使用 EventEmitter 模式
需要更灵活的控制时,可以使用自定义 Observable
网友回复
如何编写一个chrome插件实现多线程高速下载大文件?
cdn版本的vue在网页中出现typeerror错误无法找到错误代码位置怎么办?
pywebview能否使用webrtc远程控制共享桌面和摄像头?
pywebview6.0如何让窗体接受拖拽文件获取真实的文件路径?
如何在linux系统中同时能安装运行apk的安卓应用?
python有没有离线验证码识别ocr库?
各家的ai图生视频及文生视频的api价格谁最便宜?
openai、gemini、qwen3-vl、Doubao-Seed-1.6在ui截图视觉定位这款哪家更强更准?
如何在linux上创建一个沙箱隔离的目录让python使用?
pywebview如何使用浏览器自带语音识别与webspeech 的api?