Skip to content

Commit

Permalink
perf(check-tree-select): 优化大数据下勾选卡顿 (#2999) (#3000)
Browse files Browse the repository at this point in the history
* perf(check-tree-select): 优化大数据量下树选择器性能

* perf(check-tree-select): 优化大数据下勾选卡顿 (#2999)

* chore: 去掉多余文件
  • Loading branch information
zyprepare authored Sep 14, 2024
1 parent 0b71825 commit 908d6cd
Show file tree
Hide file tree
Showing 7 changed files with 40 additions and 14 deletions.
5 changes: 5 additions & 0 deletions .changeset/curly-beers-know.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@hi-ui/hiui": patch
---

perf(check-tree-select): 优化大数据下勾选卡顿
7 changes: 7 additions & 0 deletions .changeset/little-bananas-cry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@hi-ui/check-tree-select": patch
"@hi-ui/tag-input": patch
"@hi-ui/tree": patch
---

perf: 优化大数据下勾选卡顿
11 changes: 8 additions & 3 deletions packages/ui/check-tree-select/src/hooks/use-check.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,16 @@ export const useCheck = (
// 搜索时临时选中缓存数据
const [checkedNodes, setCheckedNodes] = useState<FlattedCheckTreeSelectDataItem[]>([])

const flattedDataMap = useMemo(() => new Map(flattedData.map((item) => [item.id, item])), [
flattedData,
])

const [checkedIds, trySetCheckedIds] = useUncontrolledState(
defaultCheckedIds,
checkedIdsProp,
(checkedIds, checkedNode, checked, semiCheckedIds) => {
const nextCheckedNodes = flattedData.filter((item) => checkedIds.includes(item.id))
const checkedIdsSet = new Set(checkedIds)
const nextCheckedNodes = flattedData.filter((item) => checkedIdsSet.has(item.id))
setCheckedNodes(nextCheckedNodes)

onCheck?.(checkedIds, {
Expand Down Expand Up @@ -69,12 +74,12 @@ export const useCheck = (
const proxyOnNodeCheck = useCallback(
(target: FlattedCheckTreeSelectDataItem, shouldChecked: boolean) => {
// 保证 target 来源于原数据自身,而不是tree内部
const targetNode = flattedData.find((item) => item.id === target.id)
const targetNode = flattedDataMap.get(target.id)
if (targetNode) {
onNodeCheck(targetNode, shouldChecked)
}
},
[onNodeCheck, flattedData]
[flattedDataMap, onNodeCheck]
)

return [checkedIds, trySetCheckedIds, proxyOnNodeCheck, checkedNodes, parsedCheckedIds] as const
Expand Down
8 changes: 5 additions & 3 deletions packages/ui/check-tree-select/src/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react'
import { fFindNodeById, findNestedChildren, getNodeAncestors } from '@hi-ui/tree-utils'
import { findNestedChildren, getNodeAncestors } from '@hi-ui/tree-utils'
import { isArrayNonEmpty } from '@hi-ui/type-assertion'

/**
Expand All @@ -16,11 +16,12 @@ export const processCheckedIds = (
allowCheck: (node: any) => boolean
) => {
const keySet = new Set(checkedIds)
const flattedDataMap = new Map(flattenData.map((item: any) => [item.id, item]))

switch (type) {
case 'CHILD':
return checkedIds.filter((id) => {
const node = fFindNodeById(flattenData, id)
const node = flattedDataMap.get(id) as any

if (node) {
const { children } = node
Expand All @@ -38,7 +39,8 @@ export const processCheckedIds = (

case 'PARENT':
return checkedIds.filter((id) => {
const node = fFindNodeById(flattenData, id) as any
const node = flattedDataMap.get(id) as any

if (node) {
// 向上递归遍历是否被勾选
const ancestors = getNodeAncestors(node)
Expand Down
8 changes: 4 additions & 4 deletions packages/ui/tag-input/src/TagInputMock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,10 @@ export const TagInputMock = forwardRef<HTMLDivElement | null, TagInputMockProps>
) => {
const [value, tryChangeValue] = useUncontrolledState(defaultValue, valueProp, onChange)

const tagList = useMemo(
() => value.map((id) => data.find((item) => item.id === id) || { id, title: id }),
[value, data]
)
const tagList = useMemo(() => {
const dataMap = new Map(data.map((item) => [item.id, item]))
return value.map((id) => dataMap.get(id) || { id, title: id })
}, [value, data])
const tagCount = tagList.length

const [containerWidth = 0, setContainerWidth] = useState<number>()
Expand Down
3 changes: 2 additions & 1 deletion packages/ui/tree/src/hooks/use-check.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@ export const useCheck = (
defaultCheckedIds,
checkedIdsProp,
(checkedIds, checkedNode, checked, semiCheckedIds) => {
const checkedIdsSet = new Set(checkedIds)
const nextCheckedNodes = flattedData
.filter((item) => checkedIds.includes(item.id))
.filter((item) => checkedIdsSet.has(item.id))
.map((item) => item.raw)

onCheck?.(checkedIds, {
Expand Down
12 changes: 9 additions & 3 deletions packages/ui/tree/src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,22 @@ export const processCheckedIds = (
flattenData: any
) => {
const keySet = new Set(checkedIds)
const flattedDataMap = new Map(flattenData.map((node: any) => [node.id, node]))

switch (type) {
case 'CHILD':
return checkedIds.filter((id) => {
const node = fFindNodeById(flattenData, id)
const node = flattedDataMap.get(id) as any

if (node) {
const { children } = node

if (isArrayNonEmpty(children)) {
if (children.filter((node) => !node.disabled).every((node) => keySet.has(node.id))) {
if (
children
.filter((node: any) => !node.disabled)
.every((node: any) => keySet.has(node.id))
) {
return false
}
}
Expand All @@ -59,7 +64,8 @@ export const processCheckedIds = (

case 'PARENT':
return checkedIds.filter((id) => {
const node = fFindNodeById(flattenData, id)
const node = flattedDataMap.get(id) as any

if (node) {
// 向上递归遍历是否被勾选
const ancestors = getNodeAncestors(node)
Expand Down

0 comments on commit 908d6cd

Please sign in to comment.