日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

react+tsx中使用better-scroll詳解_React

作者:ygunoil ? 更新時間: 2022-11-03 編程語言

react+tsx中使用better-scroll

首先,你要知道為什么可以滾動,原理很簡單,父容器的高度比子元素的小即可。

在這之前,我們先來看一下瀏覽器的滾動原理: 瀏覽器的滾動條大家都會遇到,當頁面內容的高度超過視口高度的時候,會出現縱向滾動條;當頁面內容的寬度超過視口寬度的時候,會出現橫向滾動條。也就是當我們的視口展示不下內容的時候,會通過滾動條的方式讓用戶滾動屏幕看到剩余的內容。

第二,你需要滾動的元素應該是父元素下的第一個子元素。

這里要注意的是,BetterScroll 默認處理容器(wrapper)的第一個子元素(content)的滾動,其它的元素都會被忽略。

第三,為什么我滿足了上面兩條,為什么還是不能滾動?可能你的content用了異步的數據,better-scroll實例化之后content的高度還是初始時的高度,這當然無法滾動,解決方法是獲取到了異步的數據之后使用refresh()更新,或是使用插件@better-scroll/observe-dom來自動更新高度, 或者observeDOM: true,

配置與初始化

這里我使用了better-scroll官方提供的幾個插件,ObserveDOMMouseWheelScrollBarPullDownPullup

大致的結構

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

欄目分類
最近更新