参考:https://blog.csdn.net/ZTJ_123/article/details/103909346

1. src/directive/scroll.js:中写入自定义指令。

import Vue from 'vue'

//全局自定义指令  给目标元素动画滚动到指定偏移位置 如果绑定值为true 则滚动到顶部
Vue.directive('scroll-top', {
  /**
   * 
   * @param {object} el 
   * @param {object} binding 
   * binding.value={
   *        allowScroll:false,是否允许滚动
   *        offset:0,滚动到距父元素上偏移量
   *        complete:()=>{},滚动结束的回调,用来初始化/还原绑定值
   * }
   */
  componentUpdated: function (el, binding, ) {
    //是否允许滚动
    let allowScroll = false
    //目标偏移
    let goalOffset = 0
    //动画完成的回调
    let completeCall = null
    //速度因子
    let divisor = 5

    //如果绑定值是boolean类型 默认滚动到顶部
    if (typeof binding.value == "boolean") {
      allowScroll = binding.value
    }
    //如果绑定值是对象类型 
    if (binding.value && typeof binding.value == "object") {
      allowScroll = binding.value.allowScroll || false
      goalOffset = binding.value.offset || 0
      completeCall = binding.value.complete
      divisor = binding.value.divisor || 5
    }

    //获取html原生元素
    const element = el.$el ? el.$el : el

    //滚动逻辑
    if (allowScroll == true) {
      //如果偏移量 和目标偏移量相等 则不滚动 并执行回调方法
      if (element.scrollTop == goalOffset) {
        if (completeCall) {
          //回调函数里记得把绑定值初始化 比如设为false
          completeCall()
        }
        return
      }

      //判断滚动方向 
      let direction = 'up'
      //目标偏移 大于当前偏移 需向上滚动 增加元素上偏移
      if (goalOffset > element.scrollTop) {
        //向上 
        direction = 'up'
      } else {
        //向下
        direction = 'down'
      }

      //获取当前偏移和目标偏移的绝对差值
      let offsetDiff = Math.abs(goalOffset - element.scrollTop)

      //计时器 滚动逻辑
      let timer = setInterval(() => {
        //计算速度  向上舍入 速度最小为 1 这样element.scrollTop == goalOffset 最后必然成立
        //注意 当offsetDiff小于divisor后 速度将恒为1 所以 divisor不不宜过大 建议设为5
        let ispeed = Math.ceil(offsetDiff / divisor)

        //计算剩余差值
        offsetDiff = offsetDiff - ispeed

        //根据滚动方向 判断偏移量是加是减
        if (direction == 'up') {
          element.scrollTop = element.scrollTop + ispeed
        } else {
          element.scrollTop = element.scrollTop - ispeed
        }

        //当前偏移 等于目标偏移 停止滚动 清除计时器 并执行回调方法
        if (element.scrollTop == goalOffset) {
          clearInterval(timer)
          if (completeCall) {
            //回调函数里记得把绑定值初始化 比如设为false
            completeCall()
          }
        }
      }, 16)
    }
  }
})

2. 全局引入自定义指令:在main.js中

import "@/directive/scroll.js"

3. 组件中使用:

<div class="my-scroll" v-scroll-top='scrollTop'>
    <div class="year-text" v-for="(item,index) in 2" :key='index*0.77+47'></div>
    <div class="year-text" :class="[selectYearItem===item && 'year-text-active']" ref='yearDom' v-for="(item,index) in yearList" :key='index*0.2+3' @click="selectYear(item,index)">{{item}}</div>
    <div class="year-text" v-for="(item,index) in 2" :key='index*0.37+41'></div>
</div>     
<script>
export default {
    data(){
        yearList:[2020,2019,2018,2017,2016,2015,2014,2013,2012,2011,2010,2009,2008,2007],
        scrollTop:false,
        selectYearItem:2020
    },
    mounted(){
        this.selectYear(this.yearList[0],0)
    },
    methods:{
        selectYear(item,index){
            this.selectYearItem = item
            this.$nextTick(()=>{
                let offset= this.$refs.yearDom[index].offsetTop-100
                this.scrollTop={
                    allowScroll: true,
                    offset:offset,
                    complete: ()=> {
                        this.scrollTop = false
                    }
                }
           })
        },
    }
}
</script>

<style lang='less' scoped>
.my-scroll{
     overflow-y: auto;
     position: absolute;
     top: 0;
     bottom: 0;
     left: 0;
     right: 0; 
     scrollbar-width: none; /* Firefox */
     -ms-overflow-style: none; /* IE 10+ */
     &::-webkit-scrollbar {
         display: none; /* Chrome Safari */
     }
}
</style>

 

  点击哪个年份,自动滚动到哪个年份。

Logo

前往低代码交流专区

更多推荐