factory.ts 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. import { getChangePart } from "../../shared";
  2. import {
  3. Entity,
  4. EntityShape,
  5. EntityTransmit,
  6. EntityTree,
  7. EntityType,
  8. EntityTypeInstance,
  9. } from "./entity";
  10. const getEntityTransmitProps = (parent: Entity): EntityTransmit => {
  11. return {
  12. root: parent.root,
  13. };
  14. };
  15. export const entityFactoryAfter = <
  16. P extends Entity,
  17. C extends Entity<any, EntityShape, EntityTree<P, C>>
  18. >(
  19. entity: C,
  20. parent?: P
  21. ) => {
  22. if (parent) {
  23. const transmit = getEntityTransmitProps(parent);
  24. for (const key in transmit) {
  25. entity[key] = parent[key];
  26. }
  27. entity.setParent(parent);
  28. }
  29. entity.init();
  30. entity.mount();
  31. if (parent?.isMounted) {
  32. entity.mounted();
  33. }
  34. };
  35. export const entityFactory = <
  36. P extends Entity,
  37. T,
  38. S extends EntityShape,
  39. C extends EntityType<T, S, EntityTree<P>>
  40. >(
  41. attrib: T,
  42. key: string,
  43. Type: C,
  44. parent?: P,
  45. extra?: (self: EntityTypeInstance<C>) => void,
  46. created?: (self: EntityTypeInstance<C>) => void
  47. ): EntityTypeInstance<C> => {
  48. const entity = new Type({
  49. attrib,
  50. key,
  51. }) as EntityTypeInstance<C>;
  52. extra && extra(entity);
  53. entityFactoryAfter(entity as any, parent);
  54. created && created(entity);
  55. return entity;
  56. };
  57. export type IncEntitys<
  58. P extends Entity,
  59. T,
  60. C extends EntityType<T, S, EntityTree<P>>,
  61. S extends EntityShape
  62. > = {
  63. adds: EntityTypeInstance<C>[];
  64. dels: EntityTypeInstance<C>[];
  65. upds: EntityTypeInstance<C>[];
  66. };
  67. export type IncEntitysFactory<
  68. P extends Entity,
  69. T,
  70. C extends EntityType<T, S, EntityTree<P>>,
  71. S extends EntityShape = EntityShape
  72. > = (attribs: T[]) => IncEntitys<P, T, C, S>;
  73. // 增量工厂
  74. export const incEntitysFactoryGenerate = <
  75. P extends Entity,
  76. T,
  77. S extends EntityShape,
  78. C extends EntityType<T, S, EntityTree<P>>
  79. >(
  80. Type: C,
  81. parent?: P,
  82. extra?: (self: EntityTypeInstance<C>) => void,
  83. created?: (self: EntityTypeInstance<C>) => void
  84. ): IncEntitysFactory<P, T, C, S> => {
  85. let oldKeys: string[] = [];
  86. let useIndex = false;
  87. let inited = false;
  88. const cache: { [key in string]: EntityTypeInstance<C> } = {};
  89. const findAttrib = (attribs: any[], key: string) => {
  90. if (useIndex) {
  91. return attribs[key];
  92. } else {
  93. return attribs.find((attrib) => attrib.id === key);
  94. }
  95. };
  96. const destory = (key: string) => {
  97. const delEntity = cache[key];
  98. delEntity.destory();
  99. delete cache[key];
  100. return delEntity;
  101. };
  102. const add = (attrib: T, key: string) => {
  103. const addEntity = entityFactory(attrib, key, Type, parent, extra, created);
  104. return (cache[key] = addEntity);
  105. };
  106. return (attribsRaw: T[]) => {
  107. const attribs = attribsRaw as any[];
  108. if (!inited && attribs.length && typeof attribs[0] === "object") {
  109. useIndex = !!attribs[0].id;
  110. inited = true;
  111. }
  112. if (
  113. !useIndex &&
  114. attribs.length &&
  115. attribs.some(
  116. (item) => typeof item !== "object" || typeof item.id !== "string"
  117. )
  118. ) {
  119. throw "attribs 不合法,缺少id";
  120. }
  121. const newKeys = attribs.map((attrib, ndx) =>
  122. useIndex ? ndx.toString() : attrib.id
  123. );
  124. if (new Set(newKeys).size !== newKeys.length) {
  125. throw "attribs 的id不合法 不可重复";
  126. }
  127. const { addPort, delPort, holdPort } = getChangePart(newKeys, oldKeys);
  128. const dels = delPort.map(destory);
  129. const adds = addPort.map((key) => add(findAttrib(attribs, key), key));
  130. const upds = holdPort.map((key) => {
  131. const newAttrib = findAttrib(attribs, key);
  132. cache[key].setAttrib(newAttrib);
  133. return cache[key];
  134. });
  135. oldKeys = newKeys;
  136. return {
  137. adds,
  138. dels,
  139. upds,
  140. };
  141. };
  142. };
  143. export type SingleEntity<
  144. P extends Entity,
  145. T,
  146. C extends EntityType<T, S, EntityTree<P>>,
  147. S extends EntityShape
  148. > = {
  149. add?: EntityTypeInstance<C>;
  150. del?: EntityTypeInstance<C>;
  151. upd?: EntityTypeInstance<C>;
  152. };
  153. export type SingleEntityFactory<
  154. P extends Entity,
  155. T,
  156. C extends EntityType<T, S, EntityTree<P>>,
  157. S extends EntityShape = EntityShape
  158. > = (data: { attrib: T; key?: string }) => SingleEntity<P, T, C, S>;
  159. export const singleEntityFactory = <
  160. P extends Entity,
  161. T,
  162. S extends EntityShape,
  163. C extends EntityType<T, S, EntityTree<P>>
  164. >(
  165. Type: C,
  166. parent?: P,
  167. extra?: (self: EntityTypeInstance<C>) => void,
  168. created?: (self: EntityTypeInstance<C>) => void
  169. ): SingleEntityFactory<P, T, C, S> => {
  170. let entity: EntityTypeInstance<C> | null = null;
  171. return ({ attrib, key }) => {
  172. const result: SingleEntity<P, T, C, S> = {};
  173. if (entity) {
  174. if (!key) {
  175. entity.destory();
  176. result.del = entity;
  177. entity = null;
  178. } else if (key !== entity.getKey()) {
  179. console.error("entity 主键更改 销毁重建");
  180. entity.destory();
  181. result.del = entity;
  182. result.add = entityFactory(attrib, key, Type, parent, extra, created);
  183. entity = result.add;
  184. } else {
  185. entity.setAttrib(attrib);
  186. result.upd = entity;
  187. }
  188. } else if (key && attrib) {
  189. result.add = entityFactory(attrib, key, Type, parent, extra, created);
  190. entity = result.add;
  191. }
  192. return result;
  193. };
  194. };