<noframes id="bhrfl"><address id="bhrfl"></address>

    <address id="bhrfl"></address>

    <noframes id="bhrfl"><address id="bhrfl"><th id="bhrfl"></th></address>

    <form id="bhrfl"><th id="bhrfl"><progress id="bhrfl"></progress></th></form>

    <em id="bhrfl"><span id="bhrfl"></span></em>

    全部
    常見問題
    產品動態
    精選推薦

    Web 實現多組件同步滾動

    管理 管理 編輯 刪除

    前言

    在日常業務開發中,我們有時會遇到多個組件需要同步滾動的場景;例如在某個頁面中存在多個相關的數據表格,用戶在滾動其中一個表格時,其他表格也同步滾動保證數據行的對齊;這個功能在數據看板、儀表盤等多種場景下都很常見。

    實現這種功能并非難事,主要思路為監聽各個組件的滾動事件,當某個組件主動滾動后將自身的滾動狀態同步給其他組件;但這種實現方式背后存在嚴重的隱患:當某個組件接收到來自其他組件的主動滾動信息,并據此對自身的滾動狀態加以同步后,該組件會被動觸發滾動事件,并將自身的滾動信息傳遞給主動滾動組件;在這種情況下,極易造成死循環,并在頁面上的表現為組件不停“抽搐”。

    思路

    要解決這個問題,我們需要理清思路;我們假設當前存在 A 和 B 兩個可滾動組件需要進行信息同步,按照上述解決方案編寫代碼后,整個事件的觸發流程如下:

    A 主動滾動 -> B 同步 A 的滾動信息 -> A 同步 B 的滾動信息 -> A 主動滾動 -> 無限循環

    而理想狀態下整個事件的觸發流程如下:

    A 主動滾動 -> B 同步 A 的滾動信息 -> A 主動滾動 -> B 同步 A 的滾動信息

    兩者中的區別在于,理想狀態下被動滾動的組件不會反復觸發滾動事件造成主動組件的滾動。要解決這個問題,我們可以通過在滾動事件中對引起滾動的來源進行區分,從而判斷是否要進行滾動信息同步。

    Coding

    首先編寫組件對應的滾動處理程序,當某個組件主動滾動時,scrollPart 為空,則將 scrollPart 設置為當前組件名稱;而主動滾動的組件再次觸發滾動時,將會同步滾動信息給其他組件,此時其他組件會被動觸發滾動事件;由于此前已將 scrollPart 設置為主動滾動事件的組件名稱,因此其他組件被動觸發滾動事件后會將 scrollPart 置空。

    在這種情況下,即使主動滾動的組件被其他組件觸發被動滾動,也不會再次進行同步。

    type ScrollPart = "compA" | "compB";
    let scrollPart: ScrollPart; // 觸發原始滾動的組件名稱
    
    // 根據組件名稱生成組件滾動事件的回調處理程序
    const scrollCallbackFactory = (key: ScrollPart) => {
        return () => {
            if (!scrollPart) {
                scrollPart = key;
            } else if (scrollPart === key) {
                syncScrollState();
            } else {
                scrollPart = undefined;
            }
        }
    }

    接下來需要添加事件監聽程序和事件信息同步程序。

    const compA = document.querySelector("#compA");
    const compB = document.querySelector("#compB");
    
    compA.addEventListener("scroll", scrollCallbackFactory("compA"));
    compA.addEventListener("scroll", scrollCallbackFactory("compB"));
    
    function syncScrollState() {
        switch (scrollPart) {
            case "compA":
                compB.scrollTop = compA.scrollTop;
                break;
            case "compB":
                compA.scrollTop = compB.scrollTop;
                break;
        }
    }

    這種處理組件同步的方法是可擴展的,支持橫向、縱向滾動以及多個組件滾動,只需給對應組件添加事件監聽,并在 syncScrollState 函數里按照對應的組件同步滾動信息即可。

    請登錄后查看

    plz 最后編輯于2025-02-26 11:45:54

    快捷回復
    回復
    回復
    回復({{post_count}}) {{!is_user ? '我的回復' :'全部回復'}}
    排序 默認正序 回復倒序 點贊倒序

    {{item.user_info.nickname ? item.user_info.nickname : item.user_name}} LV.{{ item.user_info.bbs_level }}

    作者 管理員 企業

    {{item.floor}}# 同步到gitee 已同步到gitee {{item.is_suggest == 1? '取消推薦': '推薦'}}
    {{item.is_suggest == 1? '取消推薦': '推薦'}}
    沙發 板凳 地板 {{item.floor}}#
    {{item.user_info.title || '暫無簡介'}}
    附件

    {{itemf.name}}

    {{item.created_at}}  {{item.ip_address}}
    {{item.like_count}}
    {{item.showReply ? '取消回復' : '回復'}}
    刪除
    回復
    回復

    {{itemc.user_info.nickname}}

    {{itemc.user_name}}

    回復 {{itemc.comment_user_info.nickname}}

    附件

    {{itemf.name}}

    {{itemc.created_at}}
    {{itemc.like_count}}
    {{itemc.showReply ? '取消回復' : '回復'}}
    刪除
    回復
    回復
    查看更多
    1195
    {{like_count}}
    {{collect_count}}
    添加回復 ({{post_count}})

    相關推薦

    快速安全登錄

    使用微信掃碼登錄
    {{item.label}} 加精
    {{item.label}} {{item.label}} 板塊推薦 常見問題 產品動態 精選推薦 首頁頭條 首頁動態 首頁推薦
    取 消 確 定
    回復
    回復
    問題:
    問題自動獲取的帖子內容,不準確時需要手動修改. [獲取答案]
    答案:
    提交
    bug 需求 取 消 確 定

    微信登錄/注冊

    切換手機號登錄

    {{ bind_phone ? '綁定手機' : '手機登錄'}}

    {{codeText}}
    切換微信登錄/注冊
    暫不綁定
    亚洲欧美字幕
    CRMEB客服

    CRMEB咨詢熱線 咨詢熱線

    400-8888-794

    微信掃碼咨詢

    CRMEB開源商城下載 源碼下載 CRMEB幫助文檔 幫助文檔
    返回頂部 返回頂部
    CRMEB客服