網站首頁 編程語言 正文
react+tsx中使用better-scroll
首先,你要知道為什么可以滾動,原理很簡單,父容器的高度比子元素的小即可。
在這之前,我們先來看一下瀏覽器的滾動原理: 瀏覽器的滾動條大家都會遇到,當頁面內容的高度超過視口高度的時候,會出現縱向滾動條;當頁面內容的寬度超過視口寬度的時候,會出現橫向滾動條。也就是當我們的視口展示不下內容的時候,會通過滾動條的方式讓用戶滾動屏幕看到剩余的內容。
第二,你需要滾動的元素應該是父元素下的第一個子元素。
這里要注意的是,BetterScroll 默認處理容器(wrapper)的第一個子元素(content)的滾動,其它的元素都會被忽略。
第三,為什么我滿足了上面兩條,為什么還是不能滾動?可能你的content用了異步的數據,better-scroll實例化之后content的高度還是初始時的高度,這當然無法滾動,解決方法是獲取到了異步的數據之后使用refresh()
更新,或是使用插件@better-scroll/observe-dom
來自動更新高度, 或者observeDOM: true,
配置與初始化
這里我使用了better-scroll
官方提供的幾個插件,ObserveDOM
、MouseWheel
、ScrollBar
、PullDown
和Pullup
。
大致的結構
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 Scroll
ok,準備工作完成,接下來準備better-scroll
的實例化
BetterScroll 提供了一個類,實例化的第一個參數是一個原生的 DOM 對象。當然,如果傳遞的是一個字符串,BetterScroll 內部會嘗試調用 querySelector 去獲取這個 DOM 對象。
// 外層的wrap實例 const wrapRef = useRef<HTMLDivElement>(null) // 記錄Better-scroll是否實例化,為后續掛載下拉刷新和上拉加載做準備 const initRef = useRef(false) // 存儲better-scroll的實例 const [scrollObj, setscrollObj] = useState<BScrollConstructor>() // better-scroll的配置參數 const initBScroll = () => { setscrollObj( new BScroll(wrapRef.current as HTMLDivElement, { //probeType 為 3,任何時候都派發 scroll 事件,包括調用 scrollTo 或者觸發 momentum 滾動動畫 probetype: 3, // 可以使用原生的點擊 click: true, // 檢測dom變化 observeDOM: true, // 鼠標滾輪設置 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進行實例化,以及為其添加下拉和上拉監聽函數
// 對象初始化 useEffect(() => { initBScroll() return () => { // 組件卸載時記得將其銷毀 scrollObj?.destroy() } }, []) // 下拉刷新 const pulldown = async () => { onPulldown && (await onPulldown()) setTimeout(() => { // 記得使用finishPullDown,不然你只能下拉一次 scrollObj?.finishPullDown() // 下拉之后你的content會發生變化,如果不使用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; } // 為什么監聽prop是因為這邊監聽不到外面的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[]>([]); // 一開始拉取數據 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;
原文鏈接:https://www.cnblogs.com/ygunoil/p/16672843.html
相關推薦
- 2022-08-11 GoFrame框架數據校驗之校驗結果Error接口對象_Golang
- 2022-05-27 Python?time三種時間轉換小結_python
- 2022-05-31 jQuery實現側邊導航欄及滑動電梯效果(仿淘寶)_jquery
- 2022-12-23 Kotlin擴展函數與運算符重載超詳細解析_Android
- 2022-10-04 python?Dataframe?合并與去重詳情_python
- 2022-09-21 Django?url.py?path?name同一app下路由別名定義_python
- 2022-11-29 redis的主從復制,哨兵和cluster集群
- 2022-12-06 深入了解C語言中的字符串和內存函數_C 語言
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支