滑动到Swiper列表末尾时showMore函数触发两次的修复方案咨询
滑动到Swiper列表末尾时showMore函数触发两次的修复方案咨询
嘿,我来帮你分析下这个问题~
你遇到的showMore()触发两次的情况,根源大概率是动态添加加载滑块导致的Swiper布局重计算:当loadingMorePosts为true时,你插入了一个新的SwiperSlide(加载Spinner),这会让Swiper重新计算所有滑块的位置和边界。这个布局变化可能会让Swiper误判为“再次到达列表末尾”,从而第二次触发onReachEnd事件,最终导致showMore被调用两次。
下面给你几个实用的修复方案,按推荐程度排序:
方案一:在showMore中增加状态拦截(最推荐)
最简单直接的办法,就是在showMore函数开头先检查loadingMorePosts的状态,如果当前正在加载更多内容,就直接返回,不执行后续逻辑:
const showMore = () => { // 如果正在加载更多,直接终止函数,避免重复触发 if (loadingMorePosts) return; setLoadingMorePosts(true); console.log("SHOWMORE"); setPage(prevPage => prevPage + 1); }
这个方案能从根源上阻止重复调用——不管是Swiper布局变化触发的重复事件,还是用户快速滑动导致的多次触发,都会被拦截下来。
方案二:加载时禁用Swiper触摸交互
你可以利用Swiper的allowTouchMove属性,在加载期间禁用触摸滑动,避免用户操作或DOM变化触发额外的onReachEnd事件:
<Swiper spaceBetween={10} slidesPerView={"auto"} grabCursor={true} touchMoveStopPropagation={true} onReachEnd={showMore} allowTouchMove={!loadingMorePosts} // 加载中禁用触摸操作 > {/* 原有滑块内容 */} {error ? <ErrorSign /> : postsData?.map((post: TPost) => { return <SwiperSlide key={post.id}> <PostItem key={post.id} title={post.title} body={post.body} userId={post.userId} id={post.id} /> </SwiperSlide> })} {loadingMorePosts && <SwiperSlide className='post-item-spinner' key={"spinner"}><Spinner /></SwiperSlide>} </Swiper>
这样在加载过程中,用户无法滑动Swiper,同时Swiper也不会因为布局变化误触发事件。
方案三:将加载Spinner移出Swiper组件
既然问题是添加SwiperSlide导致的布局变化,那我们可以把加载状态的DOM放在Swiper外部,避免影响它的布局计算:
<div className='post-list__postitem-view'> <Swiper spaceBetween={10} slidesPerView={"auto"} grabCursor={true} touchMoveStopPropagation={true} onReachEnd={showMore} > {error ? <ErrorSign /> : postsData?.map((post: TPost) => { return <SwiperSlide key={post.id}> <PostItem key={post.id} title={post.title} body={post.body} userId={post.userId} id={post.id} /> </SwiperSlide> })} </Swiper> {/* 把加载Spinner放在Swiper外面 */} {loadingMorePosts && <div className='post-item-spinner'><Spinner /></div>} </div>
这种修改方式彻底避免了加载状态对Swiper布局的影响,自然也就不会出现重复触发的问题了。
备注:内容来源于stack exchange,提问作者magrega
相关产品推荐
相关产品推荐

