im-聊天框的滚动条置底

562 阅读2分钟

im-聊天框的滚动条置底

在做即使通信遇到一个需求,需要将滚动条置底,记录一下解决方法

核心代码

<div class="list" ref="list">
...
</div>

<script setup>
const list = ref(null)

// 滚动到底部
const scrollListToButtom = () => {
    nextTick(() => {
        let listNode = list.value
        if (!listNode) {
            return
        }
        // 元素内容垂直滚动的像素数 = 元素内容高度
        listNode.scrollTop = listNode.scrollHeight
    })
}
</script>

此时,只要触发 scrollListToButtom方法即可将滚动条置底

当用户切换会话列表或发送消息时,触发scrollListToButtom,但是当切换会话触发scrollListToButtom时,获取到的 listNode.scrollHeight 不是节点真正的scrollHeight,而是可视范围内的高度。

解决办法:写在生命周期updated可以完美解决

写在updated,我们可以不用通过发送或切换会话触发scrollListToButtom,只需要将scrollListToButtom方法写进updated即可。

bug:如果消息中有动态加载的图片,会出现不触底的情况

onUpdated(() => {
    scrollMessageListToButtom()

    // 这里需要先执行触底函数,然后再执行一次触底函数
    // 第一次执行是因为用户切换会话列表,立刻执行触底,滚动条会显示在底部
    // 但是如果有图片未加载完成,scrollHeight是获取不到的,当图片加载完成时,滚动条位置就会有偏差,所以就需要第二次执行
    // 第二次执行的目的时等待图片加载完成,最简单的是我们可以用定时器延迟一秒再加载来解决
    // setTimeout(() => {
    //     scrollMessageListToButtom()
    // }, 1000);
    // 最好的处理方法是监控img加载完毕事件,再调用触底函数,如下:
})

const imageLoaded = computed(() => store.state.conversation.imageLoaded)


watch(imageLoaded, () => {
    scrollMessageListToButtom()
})



// 图片添加@load="onImageLoaded"
<img @load="onImageLoaded" />

// 监听图片加载完成事件
const onImageLoaded = (event) => {
    store.commit('conversation/updateImageLoaded', event)
}

完美解决!

遇到的小bug:

一开始我对scrollTop设置值时,总是设置失败,返回0,后来发现是我布局的问题,简单来说就是因为我给一个没有滚动条的元素设置滚动条的位置,导致我无法设置scrollTop。 什么时候存在滚动条? 父子DIV是嵌套关系时,子DIV高度大于父DIV时,且overflow:auto,就会出现滚动条,若overflow:hidden,超出部分被隐藏,也不会出现滚动条。注意:滚动条是属于父DIV的

补充知识点:修改滚动条样式

.list::-webkit-scrollbar {
    width: 10px;
    height: 10px;
    /**/
}

.list::-webkit-scrollbar-thumb {
    background: #444;
    border-radius: 10px;
}

.list::-webkit-scrollbar-thumb:hover {
    background: #333;
}