UNPKG

@antv/f2

Version:

Charts for mobile visualization.

281 lines 9.08 kB
import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties"; var _excluded = ["transformFrom"]; import { isArray, isBoolean, isUndefined, pick } from '@antv/util'; import Children from '../children'; import { compareRenderTree, renderJSXElement } from '../jsx'; import { render } from '../jsx/render'; import Component from './component'; import equal from './equal'; function pickElement(element) { if (!element) return element; return Children.map(element, function (item) { if (!item) return item; // 只需要这几个元素就可以了 return pick(item, ['key', 'ref', 'type', 'props']); }); } function renderShape(component, children, animate) { var container = component.container, context = component.context, updater = component.updater, __lastElement = component.__lastElement, transformFrom = component.transformFrom, componentAnimate = component.animate; // 先清空绘制内容 container.clear(); animate = isBoolean(animate) ? animate : componentAnimate; var px2hd = context.px2hd; var lastElement = __lastElement || transformFrom && transformFrom.__lastElement; // children 是 shape 的 jsx 结构, component.render() 返回的结构 var shapeElement = renderJSXElement(children, context, updater); // @ts-ignore component.__lastElement = shapeElement; var renderElement = animate !== false ? compareRenderTree(shapeElement, lastElement) : shapeElement; if (!renderElement) return null; // 生成G的节点树, 存在数组的情况是根节点有变化,之前的树删除,新的树创建 if (isArray(renderElement)) { return renderElement.map(function (element) { return render(element, container, animate, px2hd); }); } else { return render(renderElement, container, animate, px2hd); } } function setComponentAnimate(child, parent) { var parentAnimate = parent.animate; // 如果父组件不需要动画,子组件全不不执行动画 if (parentAnimate === false) { child.animate = false; return; } var childProps = child.props; var childAnimate = childProps.animate; child.animate = isBoolean(childAnimate) ? childAnimate : parentAnimate; } function getTransformComponent(component) { if (!component) return null; // @ts-ignore var __lastElement = component.__lastElement, children = component.children; if (__lastElement) { return component; } if (!children) { return null; } var componentFromChildren = null; Children.map(children, function (item) { if (componentFromChildren) return; if (!item) return; var component = getTransformComponent(item.component); if (component) { componentFromChildren = component; } }); return componentFromChildren; } function getTransformFromComponentRef(transformFromRef) { if (!transformFromRef || !transformFromRef.current) { return null; } var transformFromComponent = transformFromRef.current; return getTransformComponent(transformFromComponent); } function createComponent(parent, element) { var type = element.type, props = element.props, ref = element.ref; var container = parent.container, context = parent.context, updater = parent.updater, transformFrom = parent.transformFrom; var transformFromRef = props.transformFrom, receiveProps = _objectWithoutProperties(props, _excluded); var component; // @ts-ignore if (type.prototype && type.prototype.isF2Component) { // @ts-ignore component = new type(receiveProps, context, updater); } else { component = new Component(receiveProps, context, updater); component.render = function () { // @ts-ignore return type(this.props, context, updater); }; } // 设置ref if (ref) { ref.current = component; } // 因为view 可能在子组件,所以这里要透传到子组件 if (transformFrom) { // @ts-ignore component.transformFrom = transformFrom; } if (transformFromRef) { var transformFromComponent = transformFromRef ? getTransformFromComponentRef(transformFromRef) : null; // @ts-ignore component.transformFrom = transformFromComponent; } var zIndex = props.zIndex; // 每个组件都新建一个独立容器 component.container = container.addGroup({ zIndex: zIndex }); component.context = context; component.updater = updater; return component; } function renderComponent(component) { Children.map(component, function (item) { var lastChildren = item.children; var mount = isUndefined(lastChildren); if (mount) { if (item.willMount) item.willMount(); } else if (item.willUpdate) { item.willUpdate(); } }); Children.map(component, function (item) { var lastChildren = item.children; var mount = isUndefined(lastChildren); var newChildren = item.render(); renderChildren(item, newChildren, lastChildren); if (mount) { if (item.didMount) item.didMount(); } else if (item.didUpdate) { item.didUpdate(); } }); } function destroyElement(elements) { Children.map(elements, function (element) { if (!element) return; var component = element.component; if (!component) { return; } if (component.willUnmount) { component.willUnmount(); } destroyElement(component.children); var container = component.container; container.remove(true); if (component.didUnmount) { component.didUnmount(); } component.destroy(); }); } function diffElement(parent, nextElement, lastElement) { if (!nextElement && !lastElement) { return null; } // 删除 if (!nextElement && lastElement) { destroyElement(lastElement); return null; } // 新建 if (nextElement && !lastElement) { return nextElement; } // diff var nextType = nextElement.type, nextProps = nextElement.props; var lastType = lastElement.type, lastProps = lastElement.props, lastComponent = lastElement.component; if (nextType !== lastType) { destroyElement(lastElement); return nextElement; } // 保留component, 等下一阶段处理 nextElement.component = lastComponent; if (equal(nextProps, lastProps) && lastComponent.context === parent.context) { return null; } return nextElement; } function diff(parent, nextChildren, lastChildren) { // destroy // 生命周期的几个阶段 // should create / update // create / Receive props // willMount / willUpdate // render // didMount / didUpdate var childrenArray = []; // 1. 第一轮比较, 直接destroy的元素处理掉,destroy 的元素不需要进入下一阶段 Children.compare(nextChildren, lastChildren, function (next, last) { var element = diffElement(parent, next, last); if (element) { childrenArray = childrenArray.concat(Children.toArray(element).filter(Boolean)); } }); // 2. 处理 shouldCreate 和 shouldUpdate var shouldProcessChildren = childrenArray.filter(function (element) { var component = element.component, props = element.props; // 说明是新增的元素,需要新建 if (!component) return true; // 不需要更新 if (component.shouldUpdate && component.shouldUpdate(props) === false) { return false; } return true; }); // 3. 处理 create 和 Receive props var shouldRenderComponent = shouldProcessChildren.map(function (element) { var component = element.component; if (!component) { component = createComponent(parent, element); } else { var props = element.props; if (component.willReceiveProps) { component.willReceiveProps(props, parent.context); } var zIndex = props.zIndex; component.container.set('zIndex', zIndex); component.props = props; component.context = parent.context; } element.component = component; setComponentAnimate(component, parent); return component; }); // 4. 处理 render renderComponent(shouldRenderComponent); // 按子组件顺序渲染内容 childrenArray.forEach(function (element) { var component = element.component; var parentGroup = parent.container; parentGroup.add(component.container); }); return nextChildren; } function isContainer(children) { if (!children) return false; if (!isArray(children)) { var type = children.type; return typeof type === 'function'; } for (var i = 0, len = children.length; i < len; i++) { if (isContainer(children[i])) { return true; } } return false; } function renderChildren(parent, nextChildren, lastChildren) { // react 生成的 element 是 not extensible 的,这里新建一个新对象,并把需要的内容pick 出来 nextChildren = pickElement(nextChildren); parent.children = nextChildren; if (isContainer(nextChildren)) { nextChildren = diff(parent, nextChildren, lastChildren); } else { renderShape(parent, nextChildren); } return nextChildren; } export { renderChildren, diff, renderComponent, renderShape, destroyElement };