diff --git a/docs/tree/demo/render-child-nodes.md b/docs/tree/demo/render-child-nodes.md new file mode 100644 index 0000000000..72cd6bab5d --- /dev/null +++ b/docs/tree/demo/render-child-nodes.md @@ -0,0 +1,81 @@ +# 平铺叶子节点 + +- order: 9 + +当最后一级都是叶子节点时,平铺展示 + +:::lang=en-us +# Tile leaf nodes + +- order: 9 + +When the last level is all leaf nodes, the tiling display. +::: + +--- + +````jsx +import { Tree } from '@alifd/next'; + +const TreeNode = Tree.Node; + + +const formatDataSource = (data) => { + return data.map((it) => { + return { + ...it, + key: it.value, + children: formatDataSource(it.children || []) + }; + }); +} + +class Demo extends React.Component { + constructor(props) { + super(props); + + this.state = { + data: [] + }; + } + + componentDidMount() { + fetch('https://os.alipayobjects.com/rmsportal/ODDwqcDFTLAguOvWEolX.json') + .then(response => response.json()) + .then(data => this.setState({ data: formatDataSource([data[0]]) })) + .catch(e => console.log(e)); + } + + render() { + return { + if (nodes.filter((node) => !node.props.children || node.props.children.length === 0).length !== nodes.length) { + + } + return ; + }} defaultExpandAll dataSource={this.state.data}/>; + } +} + +ReactDOM.render(, mountNode); +```` + +```css +.custom-leaf-tree { + padding-left: 20px; + display: block; + font-size: 0; + white-space: normal; +} +.custom-leaf-tree .next-tree-switcher{ + display: none; +} + +.custom-leaf-tree .next-tree-node { + margin-left: 0 !important; + margin-right: 8px; + width: 68px; + display: inline-block; +} +``` diff --git a/docs/tree/index.en-us.md b/docs/tree/index.en-us.md index 08edc21a41..975eb37ed9 100644 --- a/docs/tree/index.en-us.md +++ b/docs/tree/index.en-us.md @@ -54,6 +54,7 @@ Folders, organizational structures, taxonomy, countries, regions, etc. Most of t | isLabelBlock | sets whether or not the node occupies the remaining space, it is generally used to add elements to the right side of each node (base flex, only Internet Explorer 10+ is supported) | Boolean | false | | isNodeBlock | set whether the node fills a row | Boolean/Object | false | | animation | whether to enable expand and collapse animation | Boolean | true | +| renderChildNodes | Render child nodes

**签名**:
Function(nodes: Array) => ReactNode
**params**:
_nodes_: {Array} child nodes
**返回值**:
{ReactNode}
| Function | - | ### Tree.Node diff --git a/docs/tree/index.md b/docs/tree/index.md index a38804e8c4..3d9a90b986 100644 --- a/docs/tree/index.md +++ b/docs/tree/index.md @@ -55,6 +55,7 @@ | isNodeBlock | 设置节点是否占满一行 | Boolean/Object | false | | animation | 是否开启展开收起动画 | Boolean | true | | focusedKey | 当前获得焦点的子菜单或菜单项 key 值 | String | - | +| renderChildNodes | 渲染子节点

**签名**:
Function(nodes: Array) => ReactNode
**参数**:
_nodes_: {Array} 所有的子节点
**返回值**:
{ReactNode} 返回节点
| Function | - | ### Tree.Node diff --git a/src/tree/view/tree-node.jsx b/src/tree/view/tree-node.jsx index 6b70addfc4..3e5ea2d98a 100644 --- a/src/tree/view/tree-node.jsx +++ b/src/tree/view/tree-node.jsx @@ -439,14 +439,24 @@ export default class TreeNode extends Component { renderChildTree(hasChildTree) { const { prefix, children, expanded, root } = this.props; - const { animation } = root.props; + const { animation, renderChildNodes } = root.props; - let childTree = - expanded && hasChildTree ? ( + if (!expanded || !hasChildTree) { + return null; + } + + let childTree; + + if (renderChildNodes) { + childTree = renderChildNodes(children); + } else { + childTree = ( - ) : null; + ); + } + if (animation) { childTree = {childTree}; } diff --git a/src/tree/view/tree.jsx b/src/tree/view/tree.jsx index c6956348a3..a41a189308 100644 --- a/src/tree/view/tree.jsx +++ b/src/tree/view/tree.jsx @@ -229,6 +229,12 @@ export default class Tree extends Component { * 当前获得焦点的子菜单或菜单项 key 值 */ focusedKey: PropTypes.string, + /** + * 渲染子节点 + * @param {Array} nodes 所有的子节点 + * @return {ReactNode} 返回节点 + */ + renderChildNodes: PropTypes.func, focusable: PropTypes.bool, autoFocus: PropTypes.bool, onItemFocus: PropTypes.func, diff --git a/test/tree/index-spec.js b/test/tree/index-spec.js index d38e800a5f..b0bfba2de4 100644 --- a/test/tree/index-spec.js +++ b/test/tree/index-spec.js @@ -284,6 +284,41 @@ describe('Tree', () => { assertTree({ dataSource }, mountNode); }); + it('should support render child nodes', () => { + ReactDOM.render( + { + if ( + nodes.filter( + (node) => !node.props.children || + node.props.children.length === 0 + ).length !== nodes.length) { + return
    {nodes}
; + } + return
    {nodes}
; + }} + > + + + + + + + + + +
, + mountNode + ); + + assert(!!document.querySelector('.custom-child-tree')); + }) + it('should support defaultExpandedKeys and onExpand', () => { let called = false; const handleExpand = (expandedKeys, extra) => { diff --git a/types/tree/index.d.ts b/types/tree/index.d.ts index 0d6e24c79a..2e3c5c4cd3 100644 --- a/types/tree/index.d.ts +++ b/types/tree/index.d.ts @@ -235,6 +235,10 @@ export interface TreeProps extends HTMLAttributesWeak, CommonProps { * 当前获得焦点的子菜单或菜单项 key 值 */ focusedKey?: string; + /** + * 渲染子节点 + */ + renderChildNodes?: (nodes: React.ReactNode) => React.ReactNode; } export default class Tree extends React.Component {