解决固钉与滚动跳转冲突的方案
问题描述
在开发过程中,我使用 el-affix
固钉组件来固定字母标题,同时希望在用户点击字母时,页面能够滚动到对应的联系人区域。然而,遇到了以下问题:
- 使用
el-affix
固钉时,字母标题在页面滚动时能够固定在屏幕顶部,但会影响到通过点击字母进行滚动跳转的功能。 - 在
scrollToLetter
方法中引用固钉元素时,发现无法正常滚动到目标字母。
其他:
- 页面中有多个字母标题(A, B, C, D, E),它们被 el-affix 固定在页面顶部。
- 初始页面加载时,默认展示字母A,并且滚动到对应区域正常工作。
- 当用户点击某个字母(比如 C)时,页面滚动到相应位置,但固钉内容依然显示为A,直到用户手动滚动时,固钉内容才更新为 C。
- el-affix 固钉的内容没有及时响应点击操作,因此固钉标题没有更新。
问题分析
出现该问题的原因在于,固钉 (el-affix
) 会将字母标题从其原位置脱离,并通过 position: sticky
固定到页面顶部。这导致了页面滚动时,元素的实际位置和 ref
的引用位置产生了偏差,从而影响了 scrollIntoView
方法的执行,无法准确找到并滚动到目标位置。而且 el-affix 固钉组件并不会根据滚动自动更新其内容(其实是没有达到滚动条件罢了),尤其是在使用 scrollIntoView 滚动页面时。
解决方案(看4)
- 保留原始
ref
用于滚动跳转
在原始字母标题上使用ref
绑定引用,以便在滚动时正确引用该元素。 - 为固钉元素添加额外的显示
将固钉的字母标题放置在el-affix
组件内,并通过offset
设置固钉的偏移量。这能够确保固钉的字母标题在页面滚动时保持在固定位置。 - 修改
scrollToLetter
方法
在点击字母时,仍然使用ref
来控制滚动,但通过修改固定字母标题的展示方式,避免了固钉组件影响滚动行为。 - 通过设置两个H4,一个是固钉,一个是滚动标识点(也就是ref对象)
具体解决看代码就明白了
<template>
<el-scrollbar>
<template v-for="(contacts, letter) in groupedContacts" :key="letter">
<!-- 普通字母标题元素 -->
<h4 :ref="(el) => (letterRefs[letter] = el)" class="letter-header">
{{ letter }} 注释掉这里!
</h4>
<!-- 固钉字母标题元素 -->
<el-affix :offset="180.1">
<h4 class="letter_header_copy">
{{ letter }}
</h4>
</el-affix>
</template>
</el-scrollbar>
</template>
<script setup>
import { ref, nextTick } from 'vue'
const letterRefs = ref({})
// 跳转到指定字母
const scrollToLetter = (letter) => {
nextTick(() => {
// 检查 letterRefs 中是否存在该字母的引用
if (letterRefs.value[letter]) {
// 获取对应的元素并滚动到该元素
letterRefs.value[letter].scrollIntoView({
behavior: "smooth",
block: "start",
})
}
})
}
</script>
<style scoped>
.letter-header {
font-size: 16px;
margin: 10px 0;
}
.letter_header_copy {
font-size: 16px;
margin: 10px 0;
}
</style>
总结
在使用 el-affix 组件时,要避免在内部使用ref属性,因为el-affix更改了元素原本的属性,使其脱离文档流了(我是这样理解的),当通过 scrollIntoView 方法能够正常滚动页面到指定字母,但固钉内容始终未能随滚动更新,而是保持为初始字母,直到手动滚动页面时才会更新。这一问题源于 el-affix 组件对 DOM 内容变化的自动响应机制,滚动到相应的距离才会显示,试着调整一下offset的值。
两个公用,隐藏其中一个显示文本就避免了将字母标题与固钉元素混合在一起无法使用的问题
版权属于:不冷
本文链接:https://www.buleng.xyz/archives/235/
转载时须注明出处及本声明