微信小程序开发中碰到在组件中监听app.globalData 中值得变化 处理相对应的数据
1.方法一 如果是简单数据 可以用Object.defineProperty 进行监听处理
Object.defineProperty 是 JavaScript 中的一个方法,用于直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。这个方法允许你精确地控制属性的特性,比如是否可写、是否可枚举、是否可配置等。
以下是 Object.defineProperty 方法的基本用法和参数说明
Object.defineProperty(obj, prop, descriptor)
-
obj:要在其上定义或修改属性的对象。 -
prop:要定义或修改的属性的名称,可以是一个字符串或Symbol。 -
descriptor:一个描述符对象,包含以下属性: -
configurable:布尔值,表示属性是否可以被删除或重新配置。 -
enumerable:布尔值,表示属性是否可以在for...in循环或Object.keys()方法中被枚举。 -
writable:布尔值,表示属性值是否可以被改变。 -
value:属性的数据值,对于数据属性是必需的。 -
get:获取属性的访问器函数,对于存取器属性是必需的。 -
set:设置属性的访问器函数,对于存取器属性是必需的。
小程序中用法
//在app.js中配置全局函数
setWatcher(targetKey, callback) {
const globalData = this.globalData;
// 如果该属性尚未被监听,则为其定义访问器
if (!globalData.hasOwnProperty(`_${targetKey}`)) {
let val = globalData[targetKey];
Object.defineProperty(globalData, targetKey, {
configurable: true,
enumerable: true,
set(value) {
val = value;
// 调用所有注册的回调函数
if (globalData._watchers && globalData._watchers[targetKey]) {
globalData._watchers[targetKey].forEach((cb) => cb(value, val));
}
},
get() {
return val;
}
});
// 初始化 watchers 存储对象
if (!globalData._watchers) {
globalData._watchers = {};
}
// 初始化该属性的回调函数数组
if (!globalData._watchers[targetKey]) {
globalData._watchers[targetKey] = [];
}
}
// 将回调函数添加到该属性的监听列表中
globalData._watchers[targetKey].push(callback);
},
//在相对应的组件中lifetimes中调用
apps.setWatcher('role', (newValue:any, oldValue:any) => {
console.log('role 已更新:', newValue);
this.setData({
userInfo: newValue
});
});
效果
2.方法二
例:
user:{ roles:{ role:0 } }需要修改role的值
可以用Proxy 对globalData进行代理
JavaScript的Proxy是一种对象代理机制,它可以在对象和函数之间添加一个中间层,从而实现对对象和函数的拦截和控制。Proxy可以用于拦截对象的读写、函数的调用、属性的枚举等操作,并在拦截时执行自定义的操作。使用Proxy可以实现各种高级功能,例如数据绑定、事件监听、缓存等。
以下是 Proxy 方法的基本用法和参数说明
let proxy = new Proxy(target, handler);
其中,target是要被代理的目标对象,handler是一个对象,用于定义拦截目标对象的各种操作的行为。handler对象可以包含以下方法:
- get(target, prop, receiver):拦截对象属性的读取操作。
- set(target, prop, value, receiver):拦截对象属性的写入操作。
- apply(target, thisArg, args):拦截函数的调用操作。
- construct(target, args, newTarget):拦截new操作符的调用操作。
- has(target, prop):拦截in操作符的调用操作。
- deleteProperty(target, prop):拦截delete操作符的调用操作。
- defineProperty(target, prop, descriptor):拦截Object.defineProperty()方法的调用操作。
- getOwnPropertyDescriptor(target, prop):拦截Object.getOwnPropertyDescriptor()方法的调用操作。
- getPrototypeOf(target):拦截Object.getPrototypeOf()方法的调用操作。
- setPrototypeOf(target, proto):拦截Object.setPrototypeOf()方法的调用操作。
- isExtensible(target):拦截Object.isExtensible()方法的调用操作。
- preventExtensions(target):拦截Object.preventExtensions()方法的调用操作。
- ownKeys(target):拦截Object.getOwnPropertyNames()、Object.getOwnPropertySymbols()、Object.keys()等方法的调用操作。
小程序中用法
//app.js中
// 代理全局数据
initGlobalDataProxy() {
const self = this;
// 递归创建代理
const createProxy = (data, path) => {
if (typeof data !== 'object' || data === null) {
return data;
}
return new Proxy(data, {
get(target, prop, receiver) {
const value = Reflect.get(target, prop, receiver);
// 如果是对象则继续代理
if (typeof value === 'object' && value !== null) {
return createProxy(value, path ? `${path}.${String(prop)}` : String(prop));
}
return value;
},
set(target, prop, value, receiver) {
const currentPath = path ? `${path}.${String(prop)}` : String(prop);
const oldValue = Reflect.get(target, prop, receiver);
const result = Reflect.set(target, prop, value, receiver);
if (oldValue !== value) {
console.log('数据变化:', currentPath, '新值:', value);
// 1. 触发精确路径监听
if (self?.globalDataListeners && self.globalDataListeners[currentPath]) {
self.globalDataListeners[currentPath].forEach((callback) => {
callback(value, currentPath);
});
}
// 2. 触发父级路径监听(例如修改 user.role 时,如果监听了 user,也会触发)
let parentPath = path;
while (parentPath) {
if (self?.globalDataListeners && self.globalDataListeners[parentPath]) {
const parentValue = parentPath.split('.').reduce((obj, key) => obj[key], self.globalData);
self.globalDataListeners[parentPath].forEach((callback) => {
callback(parentValue, parentPath);
});
}
const lastDot = parentPath.lastIndexOf('.');
parentPath = lastDot !== -1 ? parentPath.substring(0, lastDot) : '';
}
}
return result;
}
});
};
this.globalData = createProxy(this.globalData);
},
// 添加监听器
addGlobalDataListener(prop:any, callback:any) {
if (!this.globalDataListeners) {
this.globalDataListeners = {};
}
if (!this.globalDataListeners[prop]) {
this.globalDataListeners[prop] = [];
}
this.globalDataListeners[prop].push(callback);
}
//在相对应的组件中lifetimes中调用
apps.initGlobalDataProxy();
// 监听 userInfo 变化
apps.addGlobalDataListener('user', (newValue:any) => {
console.log("更改值了",newValue.roles.role)
});
效果
就可以动态更改组件的需求了 当然这只是其中几种方法 可能有的小伙伴会有更好的方法 欢迎来讨论