diff --git a/src/tree/TreeItem.tsx b/src/tree/TreeItem.tsx index 476a5fc3f9..ded073df88 100644 --- a/src/tree/TreeItem.tsx +++ b/src/tree/TreeItem.tsx @@ -8,6 +8,7 @@ import React, { DragEvent, isValidElement, useEffect, + useState, } from 'react'; import classNames from 'classnames'; import isFunction from 'lodash/isFunction'; @@ -25,6 +26,7 @@ import useConfig from '../hooks/useConfig'; import type { TdTreeProps } from './type'; import type { TreeItemProps } from './interface'; +import type { TypeTreeNodeData } from '../_common/js/tree-v1/types'; /** * 树节点组件 @@ -210,11 +212,23 @@ const TreeItem = forwardRef( const [labelDom, setRefCurrent] = useDomRefCallback(); useRipple(labelDom); + // setData需要强制刷新组件来更新数据 + const [, updateRender] = useState({}); + const renderLabel = () => { const emptyView = locale('empty'); let labelText: string | ReactNode = ''; if (label instanceof Function) { - labelText = label(node.getModel()) || emptyView; + const { setData: nodeSetData, ...rest } = node.getModel(); + labelText = + label({ + ...rest, + // 拦截setData render tree-item + setData: (value: TypeTreeNodeData) => { + nodeSetData(value); + updateRender({}); + }, + }) || emptyView; } else { labelText = node.label || emptyView; } diff --git a/src/tree/__tests__/tree.test.tsx b/src/tree/__tests__/tree.test.tsx index 2dea5c0542..fc749f67c6 100644 --- a/src/tree/__tests__/tree.test.tsx +++ b/src/tree/__tests__/tree.test.tsx @@ -320,4 +320,71 @@ describe('Tree test', () => { await mockDelay(300); expect(container.querySelectorAll('.t-loading').length).toBe(1); }); + + test('custom label', async () => { + const data = [ + { + label: '第1一段', + value: 1, + children: [ + { + label: '第二段', + value: '1-1', + }, + ], + }, + { + label: '第二段', + value: 2, + }, + ]; + const { container } = await renderTreeWithProps({ + data, + label: ({ data, setData }) => + data.isEditing ? ( + { + console.log('blur', { ...data, isEditing: false }); + setData({ ...data, label: e.target.value, isEditing: false }); + }} + onKeyDown={(e) => { + console.log('keydown', e.key); + if (e.key === 'Enter') { + setData({ ...data, label: e.currentTarget.value, isEditing: false }); + console.log('Enter setData({ ...data, name: e.target.value, isEditing: false })'); + } + if (e.key === 'Escape') { + setData({ ...data, isEditing: false }); + console.log('ESC setData({ ...data, isEditing: false })'); + } + }} + /> + ) : ( + { + e.stopPropagation(); + setData({ ...data, isEditing: true }); + }} + > + {data.label} + + ), + }); + await mockDelay(300); + expect(container.querySelector('.tree-item-span')).not.toBeNull(); + fireEvent.dblClick(container.querySelector('.tree-item-span')); + await mockDelay(300); + expect(container.querySelector('.tree-item-input')).not.toBeNull(); + fireEvent.change(container.querySelector('.tree-item-input'), { target: { value: '123' } }); + expect(container.querySelector('.tree-item-input').value).toBe('123'); + container.querySelector('.tree-item-input').focus(); + container.querySelector('.tree-item-input').blur(); + await mockDelay(300); + expect(container.querySelector('.tree-item-input')).toBeNull(); + expect(container.querySelector('.tree-item-span')).not.toBeNull(); + expect(container.querySelector('.tree-item-span').textContent).toBe('123'); + }); });