定义一个定高的显示框,不断向显示框中打印添加日志消息,每次更新时都将内容滚动至最底部。其关键步骤就是:找到被滚动的元素,然后设置其 scrollTop 等于 scrollHeight。
这里我使用了 NaiveUI 提供的 NScrollbar 组件代替了原生的滚动条:
<script setup lang="ts">
// 消息数组,可以将其自定义为一个对象数组
const messages = ref<string[]>([])
// 对 NScrollbar 组件的引用
const sbRef = ref<VueComponent>()
// 在每次页面完成更新后,并且所有异步任务都执行完之后立即滚动到最底部
onUpdated(() => nextTick(() => {
let containerRef = sbRef.value as VueComponent
containerRef = containerRef.$refs.scrollbarInstRef.$refs.containerRef
containerRef.scrollTop = containerRef.scrollHeight
}))
</script>
<template>
<NScrollbar ref="sbRef">
<p v-for="(s,i) in messages" :key="i">
{{ s }}
</p>
</NScrollbar>
</template>
上面使用了一个自定义的VueComponent
类型,因为不知道有没有现成的结合 Vue 组件和 HTMLElement 类接口的类型,所以只好自己声明一个:
import type { Component as Component$0 } from 'vue'
declare global {
type VueComponent = Component$0 &
HTMLElement & {
$refs: Record<string, VueComponent>
}
}
export {}
实际被滚动的元素可能不是很明显,尤其是使用第三方 UI 库时它可能被隐藏在了组件的内部实现中。
实际操作时可以根据子组件的层层引用,或者 DOM 查询器获取对应的被滚动元素,然后执行滚动。
复习相关的两个属性:
scrollTop 👉
内容顶部(内容需要滚动时这个顶部可能在视口外)到视口底部的距离。
一个元素垂直方向上没有滚动时,scrollTop 等于 0,而不是元素的高度。
scrollHeight 👉
元素内容的实际高度,包含不可见的区域。
在元素被滚动的过程中,scrollHeight 是恒定不变的,因为它是由元素内容决定的,与滚动到哪里没有关系。
scrollTop 是不断变化的,它直接决定了内容应该被滚动到哪个区域。
当 scrollTop 为 0 时表示内容滚动到了最顶端,当 scrollTop 变为 scrollHeight 时表示内容滚动到了最底部。
评论区