中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

antd4里table滾動如何實現

發布時間:2023-03-02 11:31:06 來源:億速云 閱讀:147 作者:iii 欄目:開發技術

本篇內容主要講解“antd4里table滾動如何實現”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“antd4里table滾動如何實現”吧!

首先antd4的table的底層實現是rc-table,就從rc-table來看看。

一、rc-table里Header、Footer、TableBody實現保持同頻滾動的方法

場景:Table內容區域大于容器Table寬度,并且Table設置了scrollX,Header、Footer都有, 才關注同頻滾動

那么是如何實現的?

  • 監聽onScroll方法獲取到滾動條向左的滾動的距離scrollLeft;

  • 同時給三個dom設置scrollLeft

二、 rc-table里的onScroll實現

先看一般的onScroll實現

  • 監聽onScroll獲取scrollLeft

  • 設置header、footer、tableBody的scrollLeft

下面是偽代碼哈

const onScroll = (e: ScrollEvent) => {
    // 拿到scrollLeft
    const scrollLeft = e.target.scrollLeft
    // 給所有的header、footer、table-body設置scrollLeft
    header.scrollLeft = scrollLeft
    footer.scrollLeft = scrollLeft
    tableBody.scrollLeft = scrollLeft
}

源碼里onScroll的實現

 const onScroll = ({
    currentTarget,
    scrollLeft,
  }: {
    currentTarget: HTMLElement;
    scrollLeft?: number;
  }) => {
    const mergedScrollLeft = typeof scrollLeft === 'number' ? scrollLeft : currentTarget.scrollLeft;

    const compareTarget = currentTarget || EMPTY_SCROLL_TARGET; 
    if (!getScrollTarget() || getScrollTarget() === compareTarget) { 
      setScrollTarget(compareTarget);
      //一個 滾動需要 控制 header、body、summary、stickyScrollBar所有同步滾動
            // header設置scrollLeft
            scrollHeaderRef.current = mergedScrollLeft
            // body 設置scrollLeft
            scrollBodyRef.current = mergedScrollLeft
    }
  };

對比兩個的實現,可以看到rc-table里的實現多了一個入參scrollLeft和一個if判斷;
為什么多了一個入參、一個判斷?繼續往下看?

三、 Header、Footer的滾動監聽

  • 用組件FixedHolder實現,給FixedHolder綁定ref;

  • 監聽的是onWheel, 不是onScroll;

為什么監聽onWheel不是onScroll?

React.useEffect(() => {
      function onWheel(e: WheelEvent) {
        // deltaX: Returns a double representing the horizontal scroll amount
        const { currentTarget, deltaX } = e as unknown as React.WheelEvent<HTMLDivElement>;
        // 避免觸發不必要滾動, 是一種優化
        if (deltaX) {
          onScroll({ currentTarget, scrollLeft: currentTarget.scrollLeft + deltaX });
          e.preventDefault();
        }
      }
      fixHolder.current?.addEventListener('wheel', onWheel);

      return () => {
        fixHolder.current?.removeEventListener('wheel', onWheel);
      };
    }, []);

不要將 onscroll 與 onwheel混淆。onwheel 是鼠標滾輪旋轉,而 onscroll 處理的是對象內部內容區的滾動事件。
當dom滿足下面任意一條的時候,不會觸發onScroll;

  • overflow:hidden

  • 滾動條不存在

FixHolder組件

設置了樣式overflow:hidden;

<div
        style={{
          overflow: 'hidden',
          ...(isSticky ? { top: stickyTopOffset, bottom: stickyBottomOffset } : {}),
        }}
        ref={setScrollRef}
        className={classNames(className, {
          [stickyClassName]: !!stickyClassName,
        })}
                />
                <table
          style={{
            tableLayout: 'fixed',
            visibility: noData || mergedColumnWidth ? null : 'hidden',
          }}
        >
          {(!noData || !maxContentScroll || allFlattenColumnsWithWidth) && (
            <ColGroup
              colWidths={mergedColumnWidth ? [...mergedColumnWidth, combinationScrollBarSize] : []}
              columCount={columCount + 1}
              columns={flattenColumnsWithScrollbar}
            />
          )}
          {children({
            ...props,
            stickyOffsets: headerStickyOffsets,
            columns: columnsWithScrollbar,
            flattenColumns: flattenColumnsWithScrollbar,
          })}
        </table>
                </div>

通過ref,調用useCallback賦值dom;利用scrollRef.current監聽wheel事件,轉成onScroll,增加入參scrollLeft;

const setScrollRef = React.useCallback((element: HTMLElement) => {
      scrollRef.current = element;
    }, []);

四、TableBody的滾動

當然是監聽onScroll事件;
給Tables設置scrollX的情況下,TableBody設置樣式{overflow-x: auto}這樣會有同頻滾動

<div
  style={
    ...scrollXStyle,
    ...scrollYStyle
  }
          onScroll={onScroll}
          ref={scrollBodyRef}
        >
          <TableComponent>
            {bodyColGroup}
            {bodyTable}
          </TableComponent>
        </div>

五、很nice的點

獲得當前正在執行的dom

const [setScrollTarget, getScrollTarget] = useTimeoutLock(null);

getScrollTarget用來獲得當前正在執行的dom
使用useState來存儲正在執行的dom; 當組件重新渲染,dom更新,此時正在執行的dom,在下一個render的時候,就變了;useRef在下一次渲染之前不重新賦值,還是保留和上一次一樣的值;
源碼里使用useRef + setTimeout實現;useRef是用來存放當前正在執行的dom;setTimeout用來節流;
其中getState獲取正在執行當前state,可能是空的;setState設置當前的State,并且在100ms以后清空設置的狀態;

export function useTimeoutLock<State>(defaultState?: State): [(state: State) => void, () => State | null] {
  const frameRef = useRef<State | null>(defaultState || null);
  const timeoutRef = useRef<number>();

  function cleanUp() {
    window.clearTimeout(timeoutRef.current);
  }

  function setState(newState: State) {
    frameRef.current = newState;
        // 清空上一次的定時器
    cleanUp();
    
    timeoutRef.current = window.setTimeout(() => {
      frameRef.current = null;
      timeoutRef.current = undefined;
    }, 100);
  }

  function getState() {
    return frameRef.current;
  }

  useEffect(() => cleanUp, []);

  return [setState, getState];
}

onScroll為什么設置if判斷

getScrollTarget()調用onScroll的之前,是否有滾動的dom; 沒有就更新;有,判斷是否和觸發onScroll是相同Dom;是,更新;目的是為了避免執行上一個onScroll的時候,下一個onScroll執行,陷入循環,就相當于節流了;hooks版本的節流

const compareTarget = currentTarget || EMPTY_SCROLL_TARGET; 
// 固定滾動項
// 在處理上一個滾動的時候,禁止下一個也滾動執行onScroll
if (!getScrollTarget() || getScrollTarget() === compareTarget) {
    setScrollTarget(compareTarget);
}

看這塊邏輯的時候,優化細節;從hooks的角度,實現節流;wheel和scroll都是滾動,但是也有區別;并且在react里支持dom綁定onScroll、onWheel。

到此,相信大家對“antd4里table滾動如何實現”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

乌拉特后旗| 乌兰县| 新竹县| 砚山县| 高台县| 永胜县| 舞钢市| 龙井市| 四子王旗| 武川县| 赤水市| 和顺县| 高唐县| 连平县| 临桂县| 木兰县| 嵊泗县| 磴口县| 张家川| 广汉市| 惠安县| 明星| 砚山县| 磴口县| 和田县| 保靖县| 唐山市| 剑阁县| 湘潭县| 外汇| 鹤壁市| 措美县| 漳州市| 施秉县| 禄劝| 鄱阳县| 施甸县| 麻阳| 仁布县| 安塞县| 仁化县|