Vue scroll 步进滚动的方法,请教优化方案

**函数的作用,用overflow元素, 内部显示完整的行.
**

    "currElement" @scroll='menuScrollX('currElement', 26)'> <li>li> ....
let scrollValue = 0 // 把本次的scrollTop,写入变量用于判断滚动方向 let scrollTimer:any = null // Y向滚动轴调整,用于完整显示 一行 function menuScrollY(elementID: string, rowHeight = 26) { // 注意点:外部overflow元素的max-height高度, 应是 rowHeight 的倍数 // elementID: overflow元素的id // rowHeight: overflow元素 内部行元素的行高 let rowNumber = 1 // 行数 const outElement = document.getElementById(elementID) as HTMLElement // 顶部不调整,但要记录 scrollValue 值 if (outElement.scrollTop == 0) { scrollValue = 0;return } // 如果 scrollTop 值 为行高的倍数 也不调整 if ((outElement.scrollTop % rowHeight) == 0) return // 根据scrollValue 值 判断滚动方向, 计算行数 if (outElement.scrollTop > scrollValue) { rowNumber = Math.ceil(outElement.scrollTop / rowHeight) // 向下滚动 } else { rowNumber = Math.floor(outElement.scrollTop / rowHeight) // 向上滚动 } // 使滚动的高度等于行高的倍数 // 问题点, 这时scrollTop 不停修正,页面会抖动 outElement.scrollTop = (rowNumber * rowHeight) console.log('rowNumber', rowNumber,scrollValue) scrollValue = outElement.scrollTop // 把本次的scrollTop,写入变量用于下次判断滚动方向 // 问题点, 滚动停下后 ,修正一次,页会抖动一次 // if (scrollTimer !== null) { clearTimeout(scrollTimer)} // scrollTimer = setTimeout(() => { // outElement.scrollTop = (rowNumber * rowHeight) // 使滚动的高度等于行高的倍数 // scrollTimer = null // }, 200) }

用seTimeout 页会抖动一次,不用滚动时, 会不停抖动,
说明我这方法有问题. 请教更好的方法
我看到网友的贴子,也指出类似的问题, 类似的方案不能平滑实现,目前没找到优化的方法

可以用mousewheel(chrome)和DOMMouseScroll(Firefox)控制鼠标滚轮事件,只会触发一次,不需要防抖,但是拖动滚动条没法触发scorll。
拖动滚动条scroll可以考虑调整容器scrollTop头为行高倍数

<style>
    #container{overflow:auto;height:260px;border:solid 1px #aaa;max-width:680px;margin:0 auto}
    #container>div.item{line-height:26px}
    #container>div.item:nth-child(2n+1){background:#eee}
    #container>div.item{text-align:center;font-weight:bold}
</style>
<div id="container">
    <script>for (var i = 0; i < 50; i++)document.write(`<div class="item">${i}</div>`)</script>
</div>
<script>
    let container = document.querySelector('#container');
    let rowHeight = 26, rowNumber = 3;
    let byMouseWheel = false;
    function handleMouseWheel(e) {
        e.preventDefault();
        //deltaY(mousewheel有)和detail(DOMMouseScroll)小于0往上滚动
        let dir = (e.deltaY || e.detail) < 0 ? -1 : 1;
        byMouseWheel = true;
        container.scrollTop += dir * rowHeight * rowNumber;
        console.log(container.scrollTop, 'mousewheel')
        setTimeout(() => { byMouseWheel = false }, 1)
    }
    container.addEventListener('mousewheel', handleMouseWheel);
    container.addEventListener('DOMMouseScroll', handleMouseWheel)
    let timer;
    function handleScroll(e) {
        if (byMouseWheel) return false;//鼠标滚轮事件不执行

        console.log(container.scrollTop, 'scroll')
        container.scrollTop -= container.scrollTop % rowHeight;//这样不会抖,但是触发多次比较耗资源

        //防抖会跳一下,这个没法控制浏览器滚动的距离。除非改成隐藏容器自动生成的滚动条,改为用DOM模拟,拖动DOM用代码控制容器滚动,比如nicescroll
        /*
        clearTimeout(timer);
        timer = setTimeout(() => {
            container.scrollTop -= container.scrollTop % rowHeight
            console.log(container.scrollTop,'scroll')
        }, 150);*/
       
    }
    container.addEventListener('scroll', handleScroll, false);
</script>


let scrollValue = 0 // 把本次的scrollTop,写入变量用于判断滚动方向
let scrollTimer:any = null
// Y向滚动轴调整,用于完整显示 一行
function menuScrollY(elementID: string, rowHeight = 26) {
    // 注意点:外部overflow元素的max-height高度, 应是 rowHeight 的倍数
    // elementID:  overflow元素的id
    // rowHeight:  overflow元素 内部行元素的行高
    let rowNumber = 1 // 行数
    const outElement = document.getElementById(elementID) as HTMLElement
    let outElementScrollTop=outElement.scrollTop;
    // 顶部不调整,但要记录 scrollValue 值
    if (outElementScrollTop == 0) { scrollValue = 0;return }
    // 如果 scrollTop 值 为行高的倍数 也不调整
    if ((outElementScrollTop % rowHeight) == 0) return
    // 根据scrollValue 值 判断滚动方向, 计算行数
    if (outElementScrollTop > scrollValue) {  
        rowNumber = Math.ceil(outElementScrollTop / rowHeight) // 向下滚动
    } else {
        rowNumber = Math.floor(outElementScrollTop / rowHeight) // 向上滚动
    }
    // 使滚动的高度等于行高的倍数
    // 问题点, 这时scrollTop 不停修正,页面会抖动
    outElementScrollTop = (rowNumber * rowHeight)  
    console.log('rowNumber', rowNumber,scrollValue)
    scrollValue = outElementScrollTop  // 把本次的scrollTop,写入变量用于下次判断滚动方向
    // 问题点, 滚动停下后 ,修正一次,页会抖动一次
   //  if (scrollTimer !== null) { clearTimeout(scrollTimer)}
   //  scrollTimer = setTimeout(() => {
    //    outElementScrollTop = (rowNumber * rowHeight) // 使滚动的高度等于行高的倍数
     //   scrollTimer = null
    // }, 200)
}

这样更节省性能

您好,我是有问必答小助手,您的问题已经有小伙伴帮您解答,感谢您对有问必答的支持与关注!
PS:问答VIP年卡 【限时加赠:IT技术图书免费领】,了解详情>>> https://vip.csdn.net/askvip?utm_source=1146287632