@antv/f2
Version:
Charts for mobile visualization.
112 lines (101 loc) • 2.61 kB
text/typescript
import { JSX } from './jsx/jsx-namespace';
import { isArray, isNil } from '@antv/util';
function cloneElement(element, props) {
if (!element) return element;
return {
...element,
props: {
...element.props,
...props,
},
};
}
function map(children: any, fn: any) {
if (!children) {
return fn(children);
}
if (isArray(children)) {
return children.map((child) => {
return map(child, fn);
});
}
return fn(children);
}
function compareArray(
nextElements: JSX.Element[],
lastElements: JSX.Element[],
callback: Function
) {
const keyed = {};
const nextLength = nextElements.length;
const lastLength = lastElements.length;
for (let i = 0, len = lastLength; i < len; i++) {
const element = lastElements[i];
if (element && !isNil(element.key)) {
const { key } = element;
keyed[key] = element;
}
}
// 比较元素
for (let i = 0, len = Math.max(nextLength, lastLength); i < len; i++) {
const element = nextElements[i];
if (!element) {
compare(element, lastElements[i], callback);
continue;
}
const { key } = element;
// 有key值定义
if (!isNil(element.key)) {
const lastElement = keyed[key];
if (lastElement) delete keyed[key];
compare(element, lastElement, callback);
continue;
}
compare(element, lastElements[i], callback);
}
// 说明是删除的元素
Object.keys(keyed).forEach((key) => {
compare(null, keyed[key], callback);
});
}
// 比较2棵树
function compare(nextElement: JSX.Element, lastElement: JSX.Element, callback: Function) {
// 有一个为空
if (!nextElement || !lastElement) {
callback(nextElement, lastElement);
return;
}
if (isArray(nextElement) || isArray(lastElement)) {
const nextElementArray = isArray(nextElement) ? nextElement : [nextElement];
const lastElementArray = isArray(lastElement) ? lastElement : [lastElement];
compareArray(nextElementArray, lastElementArray, callback);
return;
}
callback(nextElement, lastElement);
}
function toArray(element: JSX.Element): JSX.Element[] | null {
if (!element) {
return element as null;
}
if (!isArray(element)) {
return [element];
}
let newArray = [];
for (let i = 0, len = element.length; i < len; i++) {
const item = element[i];
if (isArray(item)) {
// @ts-ignore
newArray = newArray.concat(toArray(item));
} else {
newArray.push(item);
}
}
return newArray;
}
const Children = {
cloneElement,
map,
toArray,
compare,
};
export default Children;