diff --git a/packages/jsx/src/css-layout.ts b/packages/jsx/src/css-layout.ts index 2b4248f49..eebcd2dfe 100644 --- a/packages/jsx/src/css-layout.ts +++ b/packages/jsx/src/css-layout.ts @@ -1206,6 +1206,7 @@ function layoutNode(node, parentMaxWidth, parentDirection) { /* eslint-enable */ function computeLayout(node) { + if (!node) return node; const { style, children } = node; if (style) { fillNodes(node); diff --git a/packages/jsx/src/render.ts b/packages/jsx/src/render.ts index 2bbd152ea..5fe5ae992 100644 --- a/packages/jsx/src/render.ts +++ b/packages/jsx/src/render.ts @@ -3,6 +3,7 @@ import { extendMap, batch2hd } from '@ali/f2x-util'; import computeLayout from './css-layout'; import getShapeAttrs from './shape'; import getAnimation from './animation'; +import { ELEMENT_DELETE } from './elementStatus'; // 转换成布局所需要的布局树 function createNodeTree(element: any, container: any) { @@ -62,7 +63,7 @@ function mergeLayout(parent: any, layout: any) { function createElement(node: any, container: any, parentLayout: any) { - const { _cache = {}, key, ref, type, props, style, attrs, layout: originLayout, children, status } = node; + const { _cache = {}, key, ref, type, props, style, attrs, layout: originLayout, renderChildren, children: nodeChildren, status } = node; const layout = mergeLayout(parentLayout, originLayout); const elementAttrs = { @@ -81,6 +82,8 @@ function createElement(node: any, container: any, parentLayout: any) { status, attrs: elementAttrs }); + // 如果元素被删除了,就不会有renderChildren, 直接拿node.children渲染 + const children = renderChildren ? renderChildren : nodeChildren; // 只有group才需要处理children if (children && children.length) { for (let i = 0, len = children.length; i < len; i++) { @@ -102,11 +105,33 @@ function createElement(node: any, container: any, parentLayout: any) { return element; } +// 过滤删除的元素,让其不参与布局计算 +function filterDeleteElement(node) { + const { status, children } = node; + if (status === ELEMENT_DELETE) { + return null; + } + if (!children || !children.length) { + return node; + } + + const newChildren = children.filter((child) => { + return !!filterDeleteElement(child); + }); + + // 要保留引用 + node.children = newChildren; + node.renderChildren = children; + + return node; +} + export default (element: JSX.Element, container: any) => { if (!element) { return; } const nodeTree = createNodeTree(element, container); - computeLayout(nodeTree); + const computeLayoutTree = filterDeleteElement(nodeTree); + computeLayout(computeLayoutTree); return createElement(nodeTree, container, null); } diff --git a/packages/jsx/test/render.test.tsx b/packages/jsx/test/render.test.tsx index 02cdc5d0b..74f857213 100644 --- a/packages/jsx/test/render.test.tsx +++ b/packages/jsx/test/render.test.tsx @@ -1,6 +1,7 @@ import * as F2 from '@antv/f2'; import { render, jsx } from '../src'; +import { ELEMENT_DELETE } from '../src/elementStatus'; const { G } = F2; @@ -139,7 +140,7 @@ describe('render', () => { }); }); -describe.skip('render style alias', () => { +describe('render style alias', () => { it('group', () => { const container = canvas.addGroup(); const group = render( @@ -333,4 +334,137 @@ describe('layout', () => { // container.remove(true); }); + + describe('delete element', () => { + it('删除元素不参布局计算', () => { + const container = canvas.addGroup(); + const groupJSXElement = ( + + + + + + + + + ); + // 把中间的元素标记为删除 + groupJSXElement.props.children[1].status = ELEMENT_DELETE; + groupJSXElement.props.children[2].props.children[1].status = ELEMENT_DELETE; + const group = render(groupJSXElement, container); + canvas.draw(); + + const children = group.get('children'); + expect(children[0].get('attrs').x).toBe(0); + expect(children[0].get('attrs').y).toBe(0); + expect(children[0].get('attrs').width).toBe(100); + expect(children[0].get('attrs').height).toBe(200); + + expect(children[1].get('attrs').x).toBe(0); + expect(children[1].get('attrs').y).toBe(0); + expect(children[1].get('attrs').width).toBe(0); + expect(children[1].get('attrs').height).toBe(0); + + expect(children[2].get('attrs').x).toBe(100); + expect(children[2].get('attrs').y).toBe(0); + expect(children[2].get('attrs').width).toBe(100); + expect(children[2].get('attrs').height).toBe(200); + + const subChildren = children[2].get('children'); + expect(subChildren[0].get('attrs').x).toBe(100); + expect(subChildren[0].get('attrs').y).toBe(0); + expect(subChildren[0].get('attrs').width).toBe(100); + expect(subChildren[0].get('attrs').height).toBe(200); + + expect(children[1].get('attrs').x).toBe(0); + expect(children[1].get('attrs').y).toBe(0); + expect(children[1].get('attrs').width).toBe(0); + expect(children[1].get('attrs').height).toBe(0); + + }); + + it('删除元素不参布局计算-根元素', () => { + const container = canvas.addGroup(); + const groupJSXElement = ( + + + + + ); + // 把中间的元素标记为删除 + // @ts-ignore + groupJSXElement.status = ELEMENT_DELETE; + const group = render(groupJSXElement, container); + canvas.draw(); + + const children = group.get('children'); + expect(children.length).toBe(2); + expect(children[0].get('attrs').x).toBe(0); + expect(children[0].get('attrs').y).toBe(0); + expect(children[0].get('attrs').width).toBe(0); + expect(children[0].get('attrs').height).toBe(0); + + expect(children[1].get('attrs').x).toBe(0); + expect(children[1].get('attrs').y).toBe(0); + expect(children[1].get('attrs').width).toBe(0); + expect(children[1].get('attrs').height).toBe(0); + }); + }); });