autoBind.ts 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. import { Component } from "cc";
  2. const autoBindMap = new WeakMap<any, { [key: string]: { type?: any } }>();
  3. /**
  4. * 自动绑定与变量同名的子节点。
  5. * 装饰器不传参数(组件)则绑定节点,传了组件则绑定节点上的组件。
  6. * 如果传了组件,则传入的组件一定要和变量类型一致,否则绑定会失败。
  7. * 记得在组件的onLoad函数调用initAutoBindings(this)
  8. */
  9. export function auto(target: any, propertyKey: string): void;
  10. export function auto<T extends Component>(componentType: { new(): T }): (target: any, propertyKey: string) => void;
  11. export function auto<T extends Component>(componentTypeOrTarget?: { new(): T } | any, propertyKey?: string) {
  12. if (typeof componentTypeOrTarget === 'function') {
  13. return function (target: any, propertyKey: string) {
  14. if (!autoBindMap.has(target)) {
  15. autoBindMap.set(target, {});
  16. }
  17. autoBindMap.get(target)![propertyKey] = { type: componentTypeOrTarget };
  18. };
  19. } else {
  20. const target = componentTypeOrTarget;
  21. if (!autoBindMap.has(target)) {
  22. autoBindMap.set(target, {});
  23. }
  24. autoBindMap.get(target)![propertyKey!] = {};
  25. }
  26. }
  27. function buildNodeNameMap(node: any, nameMap: Map<string, any>) {
  28. nameMap.set(node.name, node);
  29. for (const child of node.children) {
  30. buildNodeNameMap(child, nameMap);
  31. }
  32. }
  33. /**
  34. * 在onLoad中调用这个函数然后才会自动绑定。initAutoBindings(this)。
  35. */
  36. export function initAutoBindings(instance: any) {
  37. const bindings = autoBindMap.get(Object.getPrototypeOf(instance));
  38. if (bindings) {
  39. const nameMap = new Map<string, any>();
  40. buildNodeNameMap(instance.node, nameMap);
  41. for (const propertyKey in bindings) {
  42. const binding = bindings[propertyKey];
  43. const node = nameMap.get(propertyKey);
  44. if (node) {
  45. if (binding.type) {
  46. instance[propertyKey] = node.getComponent(binding.type);
  47. } else {
  48. instance[propertyKey] = node;
  49. }
  50. } else {
  51. console.warn(`Node not found for propertyKey: ${propertyKey}`);
  52. }
  53. }
  54. }
  55. }