在 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
网友回复
DLNA与UPnP的区别和不同?
苏超自建抢票app,通过先预约再抽签化解高并发抢票?
python如何让给电脑在局域网中伪装成电视接收手机的投屏图片视频播放?
如何结合python+js如何自己的视频编码与加密播放直播?
python如何在电脑上通过局域网将本地视频或m3u8视频投屏电视播放?
腾讯视频爱奇艺优酷vip电影电视剧视频如何通过python绕过vip收费直接观看?
有没有可免费观看全球电视台直播m3u8地址url的合集?
有没有实现观影自由的免vip影视苹果 CMS V10 API的可用url?
python如何实时检测电脑usb插入检测报警?
如何判断真人操作的鼠标移动直线轨迹与机器操作的轨迹?