优化
This commit is contained in:
82
client/packages/design/components/VirtualChatList/index.tsx
Normal file
82
client/packages/design/components/VirtualChatList/index.tsx
Normal file
@@ -0,0 +1,82 @@
|
||||
import React, { useEffect, useMemo, useRef } from 'react';
|
||||
import { ResizeWatcher } from './ResizeWatcher';
|
||||
import { Scroller, ScrollerRef } from './Scroller';
|
||||
import { useUpdate } from 'ahooks';
|
||||
|
||||
interface VirtualChatListProps<ItemType> {
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
innerStyle?: React.CSSProperties;
|
||||
getItemKey?: (item: ItemType) => string;
|
||||
items: ItemType[];
|
||||
itemContent: (item: ItemType, index: number) => React.ReactNode;
|
||||
}
|
||||
|
||||
const defaultContainerStyle: React.CSSProperties = {
|
||||
overflow: 'hidden',
|
||||
};
|
||||
|
||||
const defaultInnerStyle: React.CSSProperties = {
|
||||
height: '100%',
|
||||
};
|
||||
|
||||
const scrollerStyle: React.CSSProperties = {
|
||||
height: '100%',
|
||||
};
|
||||
|
||||
const InternalVirtualChatList = <ItemType extends object>(
|
||||
props: VirtualChatListProps<ItemType>
|
||||
) => {
|
||||
const scrollerRef = useRef<ScrollerRef>(null);
|
||||
const itemHeightCache = useMemo(() => new Map<ItemType, number>(), []);
|
||||
const forceUpdate = useUpdate();
|
||||
const style = useMemo(
|
||||
() => ({
|
||||
...defaultContainerStyle,
|
||||
...props.style,
|
||||
}),
|
||||
[props.style]
|
||||
);
|
||||
const innerStyle = useMemo(
|
||||
() => ({
|
||||
...defaultInnerStyle,
|
||||
...props.innerStyle,
|
||||
}),
|
||||
[props.innerStyle]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
// 挂载后滚动到底部
|
||||
scrollerRef.current?.scrollToBottom();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="virtual-chat-list" style={style}>
|
||||
<Scroller ref={scrollerRef} style={scrollerStyle} innerStyle={innerStyle}>
|
||||
{props.items.map((item, i) => (
|
||||
<div
|
||||
key={props.getItemKey ? props.getItemKey(item) : i}
|
||||
className="virtual-chat-list__item"
|
||||
style={{ height: itemHeightCache.get(item) }}
|
||||
>
|
||||
<ResizeWatcher
|
||||
onResize={(size) => {
|
||||
itemHeightCache.set(item, size.height);
|
||||
forceUpdate();
|
||||
}}
|
||||
>
|
||||
{props.itemContent(item, i)}
|
||||
</ResizeWatcher>
|
||||
</div>
|
||||
))}
|
||||
</Scroller>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
type VirtualChatListInterface = typeof InternalVirtualChatList & React.FC;
|
||||
|
||||
export const VirtualChatList: VirtualChatListInterface = React.memo(
|
||||
InternalVirtualChatList
|
||||
) as any;
|
||||
VirtualChatList.displayName = 'VirtualChatList';
|
||||
Reference in New Issue
Block a user