在 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
网友回复