react+tsx中使用better-scroll詳解
react+tsx中使用better-scroll
首先,你要知道為什么可以滾動,原理很簡單,父容器的高度比子元素的小即可。
在這之前,我們先來看一下瀏覽器的滾動原理: 瀏覽器的滾動條大家都會遇到,當頁面內(nèi)容的高度超過視口高度的時候,會出現(xiàn)縱向滾動條;當頁面內(nèi)容的寬度超過視口寬度的時候,會出現(xiàn)橫向滾動條。也就是當我們的視口展示不下內(nèi)容的時候,會通過滾動條的方式讓用戶滾動屏幕看到剩余的內(nèi)容。
第二,你需要滾動的元素應該是父元素下的第一個子元素。
這里要注意的是,BetterScroll 默認處理容器(wrapper)的第一個子元素(content)的滾動,其它的元素都會被忽略。
第三,為什么我滿足了上面兩條,為什么還是不能滾動?可能你的content用了異步的數(shù)據(jù),better-scroll實例化之后content的高度還是初始時的高度,這當然無法滾動,解決方法是獲取到了異步的數(shù)據(jù)之后使用refresh()更新,或是使用插件@better-scroll/observe-dom來自動更新高度, 或者observeDOM: true,
配置與初始化
這里我使用了better-scroll官方提供的幾個插件,ObserveDOM、MouseWheel、ScrollBar、PullDown和Pullup。
大致的結(jié)構(gòu)
import BScroll from '@better-scroll/core'
import { BScrollConstructor } from '@better-scroll/core/dist/types/BScroll'
import ObserveDOM from '@better-scroll/observe-dom'
import MouseWheel from '@better-scroll/mouse-wheel'
import ScrollBar from '@better-scroll/scroll-bar'
import PullDown from '@better-scroll/pull-down'
import Pullup from '@better-scroll/pull-up'
export interface ScrollProps {
wrapHeight: string;
prop?: any;
onPullup?: Function;
onPulldown?: Function;
}
const Scroll: React.FC<ScrollProps> = ({
wrapHeight,
prop,
onPullup,
onPulldown,
children,}) => {
BScroll.use(ObserveDOM)
BScroll.use(MouseWheel)
BScroll.use(ScrollBar)
BScroll.use(PullDown)
BScroll.use(Pullup)
// ...
return (
<div className="scroll-warpper" ref={wrapRef} style={{ height: wrapHeight, overflow: 'hidden' }}>
<div className="scroll-content">
{children}
</div>
</div>
)
}
export default Scrollok,準備工作完成,接下來準備better-scroll的實例化
BetterScroll 提供了一個類,實例化的第一個參數(shù)是一個原生的 DOM 對象。當然,如果傳遞的是一個字符串,BetterScroll 內(nèi)部會嘗試調(diào)用 querySelector 去獲取這個 DOM 對象。
// 外層的wrap實例
const wrapRef = useRef<HTMLDivElement>(null)
// 記錄Better-scroll是否實例化,為后續(xù)掛載下拉刷新和上拉加載做準備
const initRef = useRef(false)
// 存儲better-scroll的實例
const [scrollObj, setscrollObj] = useState<BScrollConstructor>()
// better-scroll的配置參數(shù)
const initBScroll = () => {
setscrollObj(
new BScroll(wrapRef.current as HTMLDivElement, {
//probeType 為 3,任何時候都派發(fā) scroll 事件,包括調(diào)用 scrollTo 或者觸發(fā) momentum 滾動動畫
probetype: 3,
// 可以使用原生的點擊
click: true,
// 檢測dom變化
observeDOM: true,
// 鼠標滾輪設(shè)置
mouseWheel: {
speed: 20,
invert: false,
easeTime: 300
},
// 顯示滾動條
scrollY: true,
scrollbar: true,
// 過度動畫, 在下載更多的時候滾動條會有個過度動畫
useTransition: true,
// 下拉刷新
pullDownRefresh: {
threshold: 70,
stop: 0
},
// 上拉加載更多
pullUpLoad: {
threshold: 90,
stop: 10
}
})
)
}接著是在組件掛載階段時,將better-scroll進行實例化,以及為其添加下拉和上拉監(jiān)聽函數(shù)
// 對象初始化
useEffect(() => {
initBScroll()
return () => {
// 組件卸載時記得將其銷毀
scrollObj?.destroy()
}
}, [])
// 下拉刷新
const pulldown = async () => {
onPulldown && (await onPulldown())
setTimeout(() => {
// 記得使用finishPullDown,不然你只能下拉一次
scrollObj?.finishPullDown()
// 下拉之后你的content會發(fā)生變化,如果不使用refresh,你需要滑動一下才能刷新content的高度
scrollObj?.refresh()
}, 500)
}
// 上拉加載
const pullup = async () => {
onPullup && (await onPullup())
setTimeout(() => {
scrollObj?.finishPullUp()
scrollObj?.refresh()
}, 500)
}
// 對象事件掛載
useEffect(() => {
if (initRef.current === true) {
// 下拉刷新
// 每次更新都需要先把之前的pullingDown事件清除,不然會累加
scrollObj?.off("pullingDown");
scrollObj?.once("pullingDown", pulldown);
// 上拉加載
// 每次更新都需要先把之前的pullingUp事件清除,不然會累加
scrollObj?.off("pullingUp");
scrollObj?.once("pullingUp", pullup);
} else {
initRef.current = true;
}
// 為什么監(jiān)聽prop是因為這邊監(jiān)聽不到外面的state變化
// handlePullUp的[...state, ...res.data]中的state會中始終為一開始的[]
}, [prop]);實踐
import React, { CSSProperties, useEffect, useState, useCallback } from "react";
import Scroll from "./scroll";
import axios, { Method } from "axios";
export interface TestProps {}
interface ResponseType {
code: number;
data: any;
}
const Test: React.FC<TestProps> = () => {
const style: CSSProperties = {
width: "500px",
};
const request = (url: string, method: Method): Promise<ResponseType> => {
return new Promise((resolve, reject) => {
const options = {
url,
method,
};
axios(options)
.then((res) => {
const data = res.data as ResponseType;
resolve(data);
})
.catch((err) => reject(err));
});
};
const getData = () => request("/api/datasource", "GET");
const getMore = () => request("/api/abc", "GET");
const [state, setstate] = useState<any[]>([]);
// 一開始拉取數(shù)據(jù)
useEffect(() => {
(async function () {
const res = await getData();
console.log(res);
res.code === 0 && setstate(res.data);
})();
}, []);
const handlePullUp = useCallback(async () => {
const res = await getMore();
res.code === 0 && setstate(state.concat(res.data));
}, [state]);
async function handlePullDown() {
const res = await getData();
res.code === 0 && setstate(res.data);
}
return (
<div style={style}>
<Scroll
wrapHeight="300px"
prop={state}
onPullup={handlePullUp}
onPulldown={handlePullDown}
>
{state.map((item, idx) =>
idx % 2 === 0 ? (
<div key={idx} style={{ height: "200px", background: "red" }}>
{item}
</div>
) : (
<div key={idx} style={{ height: "200px", background: "green" }}>
{item}
</div>
)
)}
</Scroll>
</div>
);
};
export default Test;到此這篇關(guān)于react+tsx中使用better-scroll的文章就介紹到這了,更多相關(guān)react使用better-scroll內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
React父組件數(shù)據(jù)實時更新了,子組件沒有更新的問題
這篇文章主要介紹了React父組件數(shù)據(jù)實時更新了,子組件沒有更新的問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-03-03
React?Native?中處理?Android?手機吞字的解決方案
這篇文章主要介紹了React?Native?中處理?Android?手機吞字的解決方案,作者在 React Native 0.67.4 環(huán)境下,編寫了一個小 demo 來復現(xiàn)這個問題,需要的朋友可以參考下2022-08-08
詳解使用webpack+electron+reactJs開發(fā)windows桌面應用
這篇文章主要介紹了詳解使用webpack+electron+reactJs開發(fā)windows桌面應用,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-02-02
react redux中如何獲取store數(shù)據(jù)并將數(shù)據(jù)渲染出來
這篇文章主要介紹了react redux中如何獲取store數(shù)據(jù)并將數(shù)據(jù)渲染出來,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-08-08
解決react-connect中使用forwardRef遇到的問題
這篇文章主要介紹了解決react-connect中使用forwardRef遇到的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-05-05
詳解react native頁面間傳遞數(shù)據(jù)的幾種方式
這篇文章主要介紹了詳解react native頁面間傳遞數(shù)據(jù)的幾種方式,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-11-11

