最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

React虛擬列表的實(shí)現(xiàn)代碼

 更新時(shí)間:2023年08月27日 09:22:24   作者:Kakarotto  
最近看了vueuse的useVirtualList的實(shí)現(xiàn)方式,發(fā)現(xiàn)虛擬滾動(dòng)效果不錯(cuò),就嘗試著同樣的寫(xiě)法改成react版本,虛擬列表主要包含三部分組成,offset,viewcapacity,overscan,本文就給大家介紹一下React虛擬列表的實(shí)現(xiàn),需要的朋友可以參考下

最近看了vueuse的useVirtualList的實(shí)現(xiàn)方式,發(fā)現(xiàn)虛擬滾動(dòng)效果不錯(cuò),就嘗試著同樣的寫(xiě)法改成react版本。

虛擬列表主要包含三部分組成,示意圖如下:

定義一個(gè) useVirtualList 的 hook 需要接收兩個(gè)參數(shù),一是接收所有的數(shù)據(jù),二是定義一些配置參數(shù);需要返回的四個(gè)參數(shù),一是當(dāng)前加載的列表,二是獲取容器的 ref 和容器滾動(dòng)事件,三是快速定位的方法,四是內(nèi)層容器的樣式?;镜拇a結(jié)構(gòu)如下:

export type UseVirtualListOptions = {
	// 如果是每條數(shù)據(jù)的高度相同為number 否則通過(guò)方法計(jì)算高度
	itemHeight: number | ((index: number) => number);
	overscan?: number;
};
export const useVirtualList = (
	list: AllItems[],
	options: UseVirtualListOptions
): UseVirtualListReturn => {
	const containerRef = useRef(null);
	const [currentList, setCurrentList] = useState<CurrentList[]>([]);
	const [wrapperStyle, setWrapperStyle] = useState({
		width: "100%",
		height: "0px",
		marginTop: "0px",
	});
	return {
		list: currentList,
		containerProps: {
			ref: containerRef,
			onScroll: () => {},
		},
		scrollTop,
		wrapperStyle,
	};
};

因?yàn)樾枰萜鞯母叨群蜐L動(dòng)距離來(lái)計(jì)算加載的內(nèi)容,因此需要在 dom 掛載完成后執(zhí)行。

1、計(jì)算容器的的高度能顯示的數(shù)據(jù)

如果 itemHeight 類(lèi)型為 number,則可以通過(guò)容器高度 / itemHeight 來(lái)計(jì)算容器能顯示多少條數(shù)據(jù),否則需要把上一次開(kāi)始索引作為起始值,預(yù)估滾動(dòng)之后能夠在可視區(qū)域顯示多少數(shù)據(jù)。

const getViewCapacity = (containerHeight: number) => {
	if (typeof itemHeight === "number") {
		return Math.ceil(containerHeight / itemHeight);
	}
	let sum = 0;
	let capacity = 0;
	const { start = 0 } = state;
	console.log(start);
	for (let i = start; i < list.length; i++) {
		const height = itemHeight(i);
		sum += height;
		if (sum >= containerHeight) {
			capacity = i;
			break;
		}
	}
	return capacity - start;
};

2、計(jì)算滾動(dòng)偏移的數(shù)據(jù)量

如果 itemHeight 類(lèi)型為 number,則可以通過(guò)容器高度 / itemHeight 來(lái)計(jì)算滾動(dòng)偏移的數(shù)據(jù)量,否則需要對(duì)滾動(dòng)偏移的 dom 高度進(jìn)行累加,計(jì)算出偏移的數(shù)據(jù)量。

const getOffset = (scrollTop: number) => {
	if (typeof itemHeight === "number") {
		return Math.floor(scrollTop / itemHeight) + 1;
	}
	let sum = 0;
	let offset = 0;
	for (let i = 0; i < list.length; i++) {
		const height = itemHeight(i);
		sum += height;
		if (sum >= scrollTop) {
			offset = i;
			break;
		}
	}
	return offset + 1;
};

3、計(jì)算滾動(dòng)時(shí)需要加載的數(shù)據(jù)

需要加載的數(shù)據(jù)開(kāi)始位置 = 滾動(dòng)偏移量 - 預(yù)加載的數(shù)量
需要加載的數(shù)據(jù)結(jié)束位置 = 滾動(dòng)偏移量 + 可視區(qū)域顯示數(shù)據(jù)量 + 預(yù)加載數(shù)據(jù)量
如果開(kāi)始位置 < 0 則從 0 開(kāi)始,結(jié)束位置大于總數(shù)組長(zhǎng)度,則結(jié)束位置為總數(shù)據(jù)的長(zhǎng)度

const from = offset - overscan;
const to = offset + viewCapacity + overscan;
state.start = from < 0 ? 0 : from;
state.end = to > list.length ? list.length : to;
setCurrentList(() => {
	return list.slice(state.start, state.end).map((ele, index) => ({
		data: ele,
		index: index + state.start,
	}));
});

4、計(jì)算列表容器的高度和滾動(dòng)的高度

列表容器的高度 = 數(shù)據(jù)長(zhǎng)度 * 預(yù)估每條數(shù)據(jù)的高度 - 滾動(dòng)偏移的高度

因?yàn)榧虞d的數(shù)據(jù)不是每次都從 0 開(kāi)始,但每次渲染是從頂部開(kāi)始的,所以滾動(dòng)到高度大于數(shù)據(jù)的高度時(shí),數(shù)據(jù)位于可視區(qū)域的上方,此時(shí)需要設(shè)置 marginTop,讓加載的數(shù)據(jù)顯示在可視區(qū)域的頂部,但如果總高度不變,數(shù)據(jù)全部加載完成后,底部會(huì)有大面積留白。

const computedWrapperStype = () => {
	const offsetTop = getDistanceTop(state.start);
	setWrapperStyle({
		width: "100%",
		height: `${totalHeight() - offsetTop}px`,
		marginTop: `${offsetTop}px`,
	});
};

5、添加快速定位功能

當(dāng)在輸入框數(shù)據(jù)要定位的索引值時(shí),可以根據(jù)索引值計(jì)算出可視區(qū)域上方需要偏移的高度,然后重新調(diào)用計(jì)算需要加載數(shù)據(jù)開(kāi)始、結(jié)束位置的方法,即可實(shí)現(xiàn)快速定位。

const scrollTop = (index: number) => {
	if (containerRef.current) {
		(containerRef.current as HTMLDivElement).scrollTop = getDistanceTop(index);
		calculateRange();
	}
};

6、源碼地址

https://stackblitz.com/edit/vitejs-vite-oy7obm?file=src%2FApp.tsx

到此這篇關(guān)于React虛擬列表的實(shí)現(xiàn)代碼的文章就介紹到這了,更多相關(guān)React虛擬列表內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • react實(shí)現(xiàn)路由攔截的示例代碼

    react實(shí)現(xiàn)路由攔截的示例代碼

    這篇文章主要介紹react實(shí)現(xiàn)路由攔截的,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2024-02-02
  • react實(shí)現(xiàn)移動(dòng)端二級(jí)路由嵌套詳解

    react實(shí)現(xiàn)移動(dòng)端二級(jí)路由嵌套詳解

    這篇文章主要介紹了react移動(dòng)端二級(jí)路由嵌套的實(shí)現(xiàn)方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • 基于React實(shí)現(xiàn)搜索GitHub用戶(hù)功能

    基于React實(shí)現(xiàn)搜索GitHub用戶(hù)功能

    在本篇博客中,我們將介紹如何在 React 應(yīng)用中搜索 GitHub 用戶(hù)并顯示他們的信息,文中通過(guò)代碼示例給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2024-02-02
  • React?hooks中useState踩坑之異步的問(wèn)題

    React?hooks中useState踩坑之異步的問(wèn)題

    這篇文章主要介紹了React?hooks中useState踩坑之異步的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • React服務(wù)端渲染(總結(jié))

    React服務(wù)端渲染(總結(jié))

    當(dāng)我們要求渲染時(shí)間盡量快、頁(yè)面響應(yīng)速度快時(shí)就會(huì)用到服務(wù)端渲染,本篇文章主要介紹了React服務(wù)端渲染,有興趣的可以了解一下
    2017-07-07
  • 如何用webpack4.0擼單頁(yè)/多頁(yè)腳手架 (jquery, react, vue, typescript)

    如何用webpack4.0擼單頁(yè)/多頁(yè)腳手架 (jquery, react, vue, typescript)

    這篇文章主要介紹了如何用webpack4.0擼單頁(yè)/多頁(yè)腳手架 (jquery, react, vue, typescript),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-06-06
  • React useReducer終極使用教程

    React useReducer終極使用教程

    useReducer是在react V16.8推出的鉤子函數(shù),從用法層面來(lái)說(shuō)是可以代替useState。相信前期使用過(guò) React 的前端同學(xué),大都會(huì)經(jīng)歷從class語(yǔ)法向hooks用法的轉(zhuǎn)變,react的hooks編程給我們帶來(lái)了絲滑的函數(shù)式編程體驗(yàn)
    2022-10-10
  • React 合成事件的實(shí)現(xiàn)

    React 合成事件的實(shí)現(xiàn)

    本文主要介紹了React 合成事件的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2026-02-02
  • React中memo useCallback useMemo方法作用及使用場(chǎng)景

    React中memo useCallback useMemo方法作用及使用場(chǎng)景

    這篇文章主要為大家介紹了React中三個(gè)hooks方法memo useCallback useMemo的作用及使用場(chǎng)景示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2023-03-03
  • React如何使用create-react-app創(chuàng)建react項(xiàng)目

    React如何使用create-react-app創(chuàng)建react項(xiàng)目

    這篇文章主要介紹了React如何使用create-react-app創(chuàng)建react項(xiàng)目問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-03-03

最新評(píng)論

德庆县| 连城县| 凤庆县| 剑川县| 岱山县| 集安市| 潜山县| 黎城县| 军事| 新乡县| 静乐县| 秭归县| 石棉县| 三河市| 南召县| 清水河县| 曲靖市| 德令哈市| 萨嘎县| 南木林县| 江城| 保定市| 和田县| 屏东县| 阜康市| 叶城县| 宁安市| 乐山市| 竹北市| 海口市| 楚雄市| 阜南县| 玉溪市| 科技| 无为县| 施甸县| 新和县| 常熟市| 大理市| 鹿泉市| 抚顺县|