原理
使用 proxy对象处理数据,添加监听,然后递归再次添加直到全部添加完毕
代码
/**
* 给对象递归建立数据监听,可以监测每一层的每个键的变化
*
* @param {*} obj // 目标对象
* @param {*} callback //回调。通过key处理对应的变化
* @param {*} parentKey 递归用 不用传值
* @returns
*/
export default function objObserve(obj, callback, parentKey = "") {
// 创建 Proxy 对象
const proxy = new Proxy(obj, {
set(target, key, value) {
const currentKey = parentKey ? `${parentKey}.${key}` : key;
target[key] = value;
callback(currentKey, value);
return true;
}
});
for (const key in obj) {
if (typeof obj[key] === "object" && obj[key] !== null) {
obj[key] = objObserve(obj[key], callback, parentKey ? `${parentKey}.${key}` : key);
}
}
// 设置一次 防止特殊环境obj类型的数据初始化不调用 (非必须)
// activateProxy(proxy);
return proxy;
}
const activateProxy = obj => {
for (const key in obj) {
if (typeof obj[key] === "object" && obj[key] !== null) {
obj[key] = obj[key]; // 重新赋值以激活 Proxy
activateProxy(obj[key]); // 递归处理嵌套对象
}
}
return;
};
使用
这个方法不存在深度问题,多深都可以用,我最多用到第三层,如果更深层处有问题及时交流:}
//以对象内一个data为例 创建绑定
constructor(data = {}) {
super(data);
this.data = objObserve(data, this.handler);
....
...
//绑定的回调
handler(key, value) {
console.log(`属性 ${key} 的值被设置为 ${value}`, this);
let firstStr = key.split(".")[0];
switch (key) {
case "position":
this.position.set(...value);
break;
case "position.0":
this.position.x = value;
break;
case "position.1":
this.position.y = value;
break;
case "position.2":
this.position.z = value;
break;
case "rotation":
this.rotation.set(...value);
break;
case "rotation.0":
this.rotation.x = value;
break;
case "rotation.1":
this.rotation.y = value;
break;
case "rotation.2":
this.rotation.z = value;
break;
case "scale":
this.scale.set(...value);
break;
case "scale.0":
this.scale.x = value;
break;
case "scale.1":
this.scale.y = value;
break;
case "scale.2":
this.scale.z = value;
break;
default:
break;
}
if (firstStr == "config") {
this.configHandler(key, value);
}
}
效果图
这是一个3d编辑器创建场景的输出