import { _decorator, Component, find, game } from "cc"; import { Constructor } from "../core"; import { Data } from "./Data"; const { ccclass, property } = _decorator; /** * 数据系统组件,常驻节点,可创建数据、获取数据、观察数据变化 * 创建数据:g.userData = DataSystem.createData(UserData);update方法里:DataSystem.watch(g.userData,"money") && this.moneyLabel.string = g.userData.money; * @author 袁浩 */ @ccclass('DataSystem') export class DataSystem extends Component { private dataMap: Map = new Map(); private watchData: Map> = new Map>(); private watchedList: Array<{ data: Data, key: PropertyKey }> = []; start() { game.addPersistRootNode(this.node);//常驻节点 this.node.name = "DataSystem"; } /** * 数据系统对象 */ private static get thisObject(): DataSystem { let node = find("DataSystem"); return node && node.getComponent(DataSystem); } /** * 创建数据 * @param classConstructor 数据对象类型 * @returns */ static createData(classConstructor: Constructor): void { let data = new classConstructor(DataSystem.thisObject.onPropertyChange, DataSystem.thisObject); DataSystem.thisObject.dataMap.set(classConstructor, data); DataSystem.thisObject.watchData.set(data, new Map()); } /** * 获取数据 * @param classConstructor 数据对象类型 * @returns */ static getData(classConstructor: Constructor): T { return DataSystem.thisObject.dataMap.get(classConstructor) as T; } /** * 删除数据 * @param classConstructor 数据对象类型 */ static deleteData(classConstructor: Constructor): void { DataSystem.thisObject.watchData.delete(DataSystem.thisObject.dataMap.get(classConstructor)); DataSystem.thisObject.dataMap.delete(classConstructor); } /** * 观察数据,当数据产生变化时会被观察到,被观察后会在帧尾清空标记 * 注意:在watch帧的时候,改变正在watch的属性值是不会被观察到变化的 * @param data 数据对象 * @param key 数据的属性名 * @returns */ static watch(data: Data, key: PropertyKey) { let propertyKeyMap = DataSystem.thisObject.watchData.get(data); DataSystem.thisObject.watchedList.push({ data, key }); return propertyKeyMap.get(key); } lateUpdate() { for (let i = 0; i < this.watchedList.length; i++) { const watchedData = this.watchedList[i]; this.watchData.get(watchedData.data).set(watchedData.key, false); } } private onPropertyChange(data: Data, key: PropertyKey, value: any) { let propertyKeyMap = this.watchData.get(data); propertyKeyMap.set(key, true); } }