動態

詳情 返回 返回

uniapp自動滾動到底,上滑取消置底-錨點滾動 - 動態 詳情

主要通過scroll-view組件來實現,比手動js獲取高度、判斷啥的更方便,而且官方支持

滾動到底

實現思路,通過錨點滾動實現,官方支持

<view id="chat-main">
        <scroll-view class="chat-main-inner" :lower-threshold="15" :scroll-into-view="targetId" scroll-y="true" @scrolltolower="scrolltolower" @scroll="scroll">
            <view class="chat-page">
                <view class="chat-content">
           你的內容....
        </view>
         <!-- 錨點1 -->
                <view id="buttom-anchor"></view>
         <!-- 錨點2 -->
                <view id="buttom-anchor2"></view>
            </view>
        </scroll-view>
</view>

我們在scroll-view標籤內部新增兩個錨點,用於切換使用,點擊回到底部按鈕時,滾動條定位到錨點位置

const targetId = ref('');
const toContentBottom = () => {
      let idName = targetId.value == 'buttom-anchor' ? 'buttom-anchor2' : 'buttom-anchor';
        targetId.value = idName;
}

如果用户快速點擊,一個錨點是無法實現的,vue對快速執行相同事件貌似有節流,所以我們要兩個錨點來回切換

上滑取消置底

我們只需要保持這個思路即可:
1、如果滾動條置底了,那麼就一直自動置底
2、如果用户上滑了,取消自定置底
所以我們只需要判斷用户是否有上滑,如果是,則取消置底即可
scroll-view組件滾動條執行時會觸發@scroll="scroll"事件

import { ref, getCurrentInstance, onMounted } from 'vue';
const { proxy } = getCurrentInstance();
const query = uni.createSelectorQuery().in(proxy);

// 滾動時觸發
let contentDomHeight = 0
let defaultTop = 60; // 設置差異值
const isSureToBottom = ref(false);
const scroll = (e) => {
  // h = scroll-view的全部高度 - 容器高度 - 已經滾動的高度
    let h = e.detail.scrollHeight - contentDomHeight - e.detail.scrollTop;
  // 按照上面的計算方法還不能拿到完全匹配的值,這其中有個差異值,我這裏設置60
  // 如果滾動條距離底部大於兩倍差異值,説明當前滾動條不在底部
    if (h > defaultTop * 2) {
        // 不在底部
        isSureToBottom.value = false;
    } else {
    // 滾動條距離底部 小於差異值,説明在底部範圍內
        // 在底部
        isSureToBottom.value = true;
    }
};

// 獲取scroll-view組件外層的容器高度,一般是flex:1自動鋪滿視口的,所以高度可以正常拿到
const getContentDom = () => {
    query
        .select('#chat-main')
        .boundingClientRect((data) => {
      // data就是dom信息,拿到dom的高度
            contentDomHeight = data.height;
        })
        .exec();
};

onMounted(() => {
    getContentDom();
});

這樣就用户上滑取消自動置底功能就改造好了,我們在修改一下回到底部的邏輯,場景如下:
1、如果每次流式輸出,根據是否在底部標識判斷是否自動置底
2、用户可以設置強制置底功能,只需在toContentBottom(true)即可,否則根據滾動條位置自動判斷
3、toContentBottom事件是一個全局響應的事件,這裏我通過$mitt插件來實現全局事件監聽

const targetId = ref('');
// 回到底部
proxy.$mitt.on('toContentBottom', (e) => {
    if (isSureToBottom.value || e) {
        if (e) isSureToBottom.value = e;
        let idName = targetId.value == 'buttom-anchor' ? 'buttom-anchor2' : 'buttom-anchor';
        targetId.value = idName;
    }
});

頁面使用

import { getCurrentInstance } from 'vue';

const toContentBottom = (state) => {
    nextTick(() => {
        proxy.$mitt.emit('toContentBottom', state);
    });
};

// 在對應需要置底的位置調用即可
toContentBottom();

參考文檔:
scroll-view
獲取節點信息

user avatar zhuifengdekukafei 頭像
點贊 1 用戶, 點贊了這篇動態!
點贊

Add a new 評論

Some HTML is okay.