需求:swiper自动滚动,且数据是从ws接口取的,每秒都会更新,需要保证在滚动的时候始终显示当前数据,不出现突然变成别的数据的情况
我写的是手机端的页面 所以一屏只出现1.5条数据
html部分
const options = {
observer: true,
observeParents: true,
speed: 1500,
loop: true,
slidesPerView: 'auto',
spaceBetween: 10,
freeMode: true,
autoplay: {
delay: 1500,
stopOnLastSlide: false,
disableOnInteraction: false,
},
} as const;
const swiperRef = useRef<SwiperType | null>(null);
const [currentIndex, setCurrentIndex] = useState(0);
// 这是从ws接口取过来的数据
const { socketData: solSocketData } = useGetSolBroadcast({
currentIndex,
});
return (
<div>
{!!realData.length && realData.length > 1 && (
<Swiper
centeredSlides={false}
modules={[Autoplay]}
{...options}
onInit={(swiper) => {
swiperRef.current = swiper;
}}
onSlideChange={(v) => setCurrentIndex(v.realIndex)}
>
{realData.map((item, i) => (
<SwiperSlide
// key一定得是索引值
key={i}
style={{
width: `${item.width}px`,
}}
>
<div
style={{
width: `${item.width}px`,
}}
>
{item.data}
</div>
</SwiperSlide>
))}
</Swiper>
)}
</div>
);
获取数据的部分
import { useThrottleEffect } from 'ahooks';
export function useGetSolBroadcast({
currentIndex,
}: {
currentIndex: number;
}) {
// 传给swiper组件的数据
const [socketData, setSocketData] = useState<SocketData>([]);
// 从ws接口取到的数据
const { messageHistory } = useSolWebSocketStore();
// 最多显示几条数据
const limit = 8;
useThrottleEffect(
() => {
// 把数据转换成需要的格式
const parsed = messageHistory
.map((item) => {
return parseMessage({
type: item.is_buy ? MessageType.Buy : MessageType.Sell,
data: item,
});
})
.filter((item) => item !== undefined);
if (messageHistory.length < limit) {
// 当数据量少于显示的数量上限时 直接赋值
setSocketData(parsed);
} else if (messageHistory.length >= limit) {
setSocketData((pre) => setNewData(pre, parsed));
}
},
[messageHistory, currentIndex],
{ trailing: false, wait: socketData.length < limit ? 1000 : 3000 },
);
const setNewData = (pre: SocketData, messageList: SocketData) => {
// 避免新取到的数据和已有数据重复
const list = messageList
?.filter((item) => !pre?.find((cItem) => cItem?.id === item?.id || cItem?.user === item?.user))
.filter((item) => item !== undefined);
if (isNumber(currentIndex)) {
// 保持当前index-1, index, index+1对应的数据不变 其他索引的数据替换成新的
if (currentIndex === 0) {
return [pre[0], pre[1], ...list.slice(0, limit - 3), pre[pre.length - 1]];
} else if (currentIndex === limit - 1) {
return [pre[0], ...list.slice(0, limit - 3), ...pre.slice(-2)];
} else {
return [
...list.slice(0, currentIndex - 1),
...pre.slice(currentIndex - 1, currentIndex + 2),
...list.slice(currentIndex - 1, limit - 3),
];
}
}
return [];
};
return { socketData };
}