🎈 perf(购物页面): 改善滚动列表的加载

This commit is contained in:
xuan 2022-10-19 11:02:19 +08:00
parent 9a759f67f1
commit ea6c45e560
4 changed files with 47 additions and 35 deletions

View File

@ -61,16 +61,16 @@ export const getFilterData = (val = {}, arr: string[] = []) => {
* @param {*} object * @param {*} object
* @returns * @returns
*/ */
export const copyObject = (object) => { export const copyObject = object => {
if (object.constructor == Object) { if (object.constructor == Object) {
let keys = Object.keys(object) let keys = Object.keys(object)
let newObject = {} let newObject = {}
keys.map((key) => { keys.map(key => {
newObject[key] = copyObject(object[key]) newObject[key] = copyObject(object[key])
}) })
return newObject return newObject
} else if (object.constructor == Array) { } else if (object.constructor == Array) {
return object.map((item) => { return object.map(item => {
return copyObject(item) return copyObject(item)
}) })
} else { } else {
@ -93,9 +93,17 @@ export const copyObject = (object) => {
export const screenshot = (url, suffix = '!w200') => { export const screenshot = (url, suffix = '!w200') => {
return url + suffix return url + suffix
} }
interface DataLoadingStatus {
list: any[]
total: number
status: boolean
}
//获取数据加载状态 //0:数据从无到有加载数据1没有任何数据 2下拉加载3下拉没有数据 //获取数据加载状态 //0:数据从无到有加载数据1没有任何数据 2下拉加载3下拉没有数据
export const dataLoadingStatus = ({ list = [], total = 0, status = false }: { list: any[]; total: number; status: true | false }) => { export const dataLoadingStatus = ({ list = [], total = 0, status = true }: DataLoadingStatus) => {
// 类型校验
if (Object.prototype.toString.call(list) !== '[object Array]') {
list = []
}
if (list.length == 0 && status) { if (list.length == 0 && status) {
return 0 return 0
} else if (list.length == 0 && !status) { } else if (list.length == 0 && !status) {
@ -107,7 +115,6 @@ export const dataLoadingStatus = ({ list = [], total = 0, status = false }: { li
} }
} }
function delay(delayTime = 25): Promise<null> { function delay(delayTime = 25): Promise<null> {
return new Promise(resolve => { return new Promise(resolve => {
setTimeout(() => { setTimeout(() => {
@ -117,10 +124,7 @@ function delay(delayTime = 25): Promise<null> {
}) })
} }
export function delayQuerySelector( export function delayQuerySelector(selectorStr: string, delayTime = 500): Promise<any[]> {
selectorStr: string,
delayTime = 500
): Promise<any[]> {
return new Promise(resolve => { return new Promise(resolve => {
const selector: SelectorQuery = Taro.createSelectorQuery() const selector: SelectorQuery = Taro.createSelectorQuery()
delay(delayTime).then(() => { delay(delayTime).then(() => {
@ -134,7 +138,6 @@ export function delayQuerySelector(
}) })
} }
//全局分享监听 //全局分享监听
export const shareShop = () => { export const shareShop = () => {
const page = Taro.getCurrentInstance().page const page = Taro.getCurrentInstance().page
@ -143,7 +146,7 @@ export const shareShop = () => {
analysisShortCodeApi(page.options.share) analysisShortCodeApi(page.options.share)
} }
if (page && page.onShareAppMessage) { if (page && page.onShareAppMessage) {
page.onShareAppMessage = (res) => { page.onShareAppMessage = res => {
let path = '' let path = ''
let title = '' let title = ''
let imageUrl = '' let imageUrl = ''
@ -170,5 +173,3 @@ export const shareShop = () => {
} }
} }
} }

View File

@ -1,10 +1,10 @@
import { ScrollView, View } from "@tarojs/components" import { ScrollView, View } from '@tarojs/components'
import React, { memo, ReactNode, useMemo, useState } from "react" import React, { memo, ReactNode, useMemo, useState } from 'react'
import style from "./index.module.scss" import style from './index.module.scss'
import DotLoading from "@/components/dotLoading" import DotLoading from '@/components/dotLoading'
import LoadingCard from "../loadingCard" import LoadingCard from '../loadingCard'
export type StatusParam = 0|1|2|3 export type StatusParam = 0 | 1 | 2 | 3
type Params = { type Params = {
styleObj?: React.CSSProperties styleObj?: React.CSSProperties
@ -36,7 +36,7 @@ export default memo(
selfOnRefresherRefresh, selfOnRefresherRefresh,
selfOnRefresherRestore, selfOnRefresherRestore,
selfOnRefresherAbort, selfOnRefresherAbort,
safeAreaInsetBottom=true, safeAreaInsetBottom = true,
enableLoadMoreStatus = true, enableLoadMoreStatus = true,
children, children,
lowerThresholdNum = 5, lowerThresholdNum = 5,
@ -76,28 +76,29 @@ export default memo(
} }
}, [statusMore]) }, [statusMore])
const component = () => { const component = () => {
if(enableLoadMoreStatus){ if (enableLoadMoreStatus) {
if (!moreStatus){ if (!moreStatus) {
return ( return (
<View style={{ paddingBottom: paddingBottom + 'rpx' }} className={style.scrollViewCon}> <View style={{ paddingBottom: paddingBottom + 'rpx' }} className={style.scrollViewCon}>
{children} {children}
</View> </View>
) )
}else{ } else {
return ( return (
<> <>
{(statusMore == 2 || statusMore == 3) && ( {(statusMore == 2 || statusMore == 3) && (
<View style={{ paddingBottom: paddingBottom + 'rpx' }} className={style.scrollViewCon}> <View style={{ paddingBottom: paddingBottom + 'rpx' }} className={style.scrollViewCon}>
{children} {children}
<View className={style.infinite_scroll}> <View className={style.infinite_scroll}>
{(statusMore == 2 && ( {statusMore == 2 ? (
<View className={style.loading_more}> <View className={style.loading_more}>
<DotLoading /> <DotLoading />
</View> </View>
)) || <View className={style.noMore}></View>} ) : (
<View className={style.noMore}></View>
)}
</View> </View>
</View> </View>
)} )}
@ -106,8 +107,7 @@ export default memo(
</> </>
) )
} }
} else {
}else{
return ( return (
<View style={{ paddingBottom: paddingBottom + 'rpx' }} className={style.scrollViewCon}> <View style={{ paddingBottom: paddingBottom + 'rpx' }} className={style.scrollViewCon}>
{children} {children}

View File

@ -1,7 +1,7 @@
import Search from '@/components/search' import Search from '@/components/search'
import { View } from '@tarojs/components' import { View } from '@tarojs/components'
import Taro, { useDidShow } from '@tarojs/taro' import Taro, { useDidShow } from '@tarojs/taro'
import { FC, memo, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react' import { FC, memo, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState, useTransition } from 'react'
import styles from './index.module.scss' import styles from './index.module.scss'
import classnames from 'classnames' import classnames from 'classnames'
import IconText from '@/components/iconText' import IconText from '@/components/iconText'
@ -15,6 +15,7 @@ import { dataLoadingStatus, debounce, getFilterData } from '@/common/util'
import { ShoppingProvider } from './components/shoppingCart/index' import { ShoppingProvider } from './components/shoppingCart/index'
import { Goods, ShoppingDispatchType, useShoppingDispatch, useShoppingState } from './context' import { Goods, ShoppingDispatchType, useShoppingDispatch, useShoppingState } from './context'
import { alert, goLink, isEmptyObject } from '@/common/common' import { alert, goLink, isEmptyObject } from '@/common/common'
import LoadingCard from '@/components/loadingCard'
export const Shopping: FC = memo(() => { export const Shopping: FC = memo(() => {
// 计算总的预估金额 // 计算总的预估金额
@ -87,7 +88,9 @@ const ShoppingCartContainer: FC<InternalContainer> = () => {
//数据加载状态 //数据加载状态
const statusMore = useMemo(() => { const statusMore = useMemo(() => {
return dataLoadingStatus({ list: shoppingCartData.list, total: shoppingCartData.total, status: state.loading }) const status = dataLoadingStatus({ list: shoppingCartData.list, total: shoppingCartData.total, status: state.loading })
console.log('status==>', status)
return status
}, [shoppingCartData, state]) }, [shoppingCartData, state])
// useLayoutEffect 执行在DOM更新之后浏览器绘制之前 如果放在 useEffect 里面会产生多一次不必要的回流和重绘,可能会引起视图闪现 // useLayoutEffect 执行在DOM更新之后浏览器绘制之前 如果放在 useEffect 里面会产生多一次不必要的回流和重绘,可能会引起视图闪现
@ -112,8 +115,12 @@ const ShoppingCartContainer: FC<InternalContainer> = () => {
})() })()
}, []) }, [])
const [isPending, startTransition] = useTransition()
useEffect(() => { useEffect(() => {
setShoppingCartData({ list: state.data, total: state.data.length }) startTransition(() => {
setShoppingCartData({ list: state.data, total: state.data.length })
})
}, [state]) }, [state])
// 结算 // 结算
@ -228,10 +235,14 @@ const ShoppingCartContainer: FC<InternalContainer> = () => {
<View className={classnames('flex-item', 'flex-col', styles['shopping--context'])}> <View className={classnames('flex-item', 'flex-col', styles['shopping--context'])}>
<View className={classnames(styles.shopping__list__container, 'flex-item')} style={{ height: listHeightRef.current }}> <View className={classnames(styles.shopping__list__container, 'flex-item')} style={{ height: listHeightRef.current }}>
<InfiniteScroll statusMore={statusMore} refresherEnabled={true} selfOnRefresherRefresh={handleRefresh} refresherTriggered={refreshStatus}> <InfiniteScroll statusMore={statusMore} refresherEnabled={true} selfOnRefresherRefresh={handleRefresh} refresherTriggered={refreshStatus}>
{!!shoppingCartData?.list?.length && {isPending ? (
<LoadingCard />
) : (
!!shoppingCartData?.list?.length &&
shoppingCartData?.list?.map((item, index) => { shoppingCartData?.list?.map((item, index) => {
return <ItemList itemData={item} key={index}></ItemList> return <ItemList itemData={item} key={index}></ItemList>
})} })
)}
</InfiniteScroll> </InfiniteScroll>
</View> </View>
</View> </View>

View File

@ -110,7 +110,7 @@ export const useRequest = (
success: false, // 请求是否成功 success: false, // 请求是否成功
data: {}, data: {},
msg: '', msg: '',
loading: false, loading: true,
error: null, error: null,
query: {}, query: {},
filter: null, filter: null,