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


