UNPKG

2.61 kBPlain TextView Raw
1import { JSX } from './jsx/jsx-namespace';
2import { isArray, isNil } from '@antv/util';
3
4function cloneElement(element, props) {
5 if (!element) return element;
6 return {
7 ...element,
8 props: {
9 ...element.props,
10 ...props,
11 },
12 };
13}
14
15function map(children: any, fn: any) {
16 if (!children) {
17 return fn(children);
18 }
19 if (isArray(children)) {
20 return children.map((child) => {
21 return map(child, fn);
22 });
23 }
24 return fn(children);
25}
26
27function compareArray(
28 nextElements: JSX.Element[],
29 lastElements: JSX.Element[],
30 callback: Function
31) {
32 const keyed = {};
33 const nextLength = nextElements.length;
34 const lastLength = lastElements.length;
35 for (let i = 0, len = lastLength; i < len; i++) {
36 const element = lastElements[i];
37 if (element && !isNil(element.key)) {
38 const { key } = element;
39 keyed[key] = element;
40 }
41 }
42
43 // 比较元素
44 for (let i = 0, len = Math.max(nextLength, lastLength); i < len; i++) {
45 const element = nextElements[i];
46 if (!element) {
47 compare(element, lastElements[i], callback);
48 continue;
49 }
50 const { key } = element;
51 // 有key值定义
52 if (!isNil(element.key)) {
53 const lastElement = keyed[key];
54 if (lastElement) delete keyed[key];
55 compare(element, lastElement, callback);
56 continue;
57 }
58 compare(element, lastElements[i], callback);
59 }
60 // 说明是删除的元素
61 Object.keys(keyed).forEach((key) => {
62 compare(null, keyed[key], callback);
63 });
64}
65
66// 比较2棵树
67function compare(nextElement: JSX.Element, lastElement: JSX.Element, callback: Function) {
68 // 有一个为空
69 if (!nextElement || !lastElement) {
70 callback(nextElement, lastElement);
71 return;
72 }
73
74 if (isArray(nextElement) || isArray(lastElement)) {
75 const nextElementArray = isArray(nextElement) ? nextElement : [nextElement];
76 const lastElementArray = isArray(lastElement) ? lastElement : [lastElement];
77 compareArray(nextElementArray, lastElementArray, callback);
78 return;
79 }
80
81 callback(nextElement, lastElement);
82}
83
84function toArray(element: JSX.Element): JSX.Element[] | null {
85 if (!element) {
86 return element as null;
87 }
88 if (!isArray(element)) {
89 return [element];
90 }
91 let newArray = [];
92 for (let i = 0, len = element.length; i < len; i++) {
93 const item = element[i];
94 if (isArray(item)) {
95 // @ts-ignore
96 newArray = newArray.concat(toArray(item));
97 } else {
98 newArray.push(item);
99 }
100 }
101 return newArray;
102}
103
104const Children = {
105 cloneElement,
106 map,
107 toArray,
108 compare,
109};
110
111export default Children;