vue锚点跳转scrollIntoView()方法

滚动到某个特定元素 

scrollIntoView();这个方法不用获取右边小标题的高度,啥都不用,有id或者class就行啦,几乎可以满足你锚点跳转的所有需求,对齐方式,以及平滑滚动了

这里是v-for循环出来需要点击跳转到对应div的事件

<p> v-for="(value,index) in data" @click="scrollToPosition(index)">{{...}}</p>  

这就是你点击scrollToPosition事件需要滚动对应的div

<div> v-for="(value,index) in data" class="roll">{{...}}</div>  

js部分

methods:{
  scrollToPosition(index){
     document.getElementsByClassName('roll')[index].scrollIntoView()
}

这样就利用scrollIntoView()简单实现了一个锚点跳转,下边来看一个scrollIntoView中的一些属性

  • scrollIntoView(true)相等于scrollIntoView();元素的顶端将和其所在滚动区的可视区域的顶端对齐

为true时相应的 scrollIntoViewOptions: {block: “start”, inline: “nearest”}。这是这个参数的默认值。

  • scrollIntoView(false)元素的底端将和其所在滚动区的可视区域的底端对齐

为false时相应的scrollIntoViewOptions: {block: “end”, inline: “nearest”}。

同时他的参数也可以是一个object对象

  scrollIntoView({
  behavior:auto //定义动画过渡效果"auto"或 "smooth" 之一。默认为 "auto"。
  block:start//定义垂直方向的对齐, "start", "center", "end", 或 "nearest"之一。默认为 "start"。
  inline:nearest//"start", "center", "end", 或 "nearest"之一。默认为 "nearest"。
  })

其中smooth是平滑滚动 start和end是目标滚动到的位置

注意:

兼容性的问题多数主流浏览器已经支持其基本功能,也就是说,使用true,false两个参数,来实现木讷的定位(没有滚动动画)是没有任何问题的,但是传入object参数时,就不得不说一句,IE各种版本会直接忽略,全部看成true参数属性,如果想看到滚动动画,就只有火狐和chrome 

一个简单的vue锚点跳转demo

拿去直接粘贴就可

<template>
  <div class="auto-adjust-edit" >
    <!-- 按钮 -->
    <div class="operation-btn">
        <div class="btn-item" v-for="(item, index) in partList" :key="index" @click="jump(index)"
            :style="{background: activeStep === index ? '#eeeeee' : '#ffffff'}">{{item}}
        </div>
    </div>
    <!-- 滚动区域 -->
    <div class="scroll-content" @scroll="onScroll">
      <div class="scroll-item">
          <div class="part-title">基本信息</div>
      </div>
      <div class="scroll-item">
          <div class="part-title">风险控制</div>
      </div>
      <div class="scroll-item">
          <div class="part-title">成本控制</div>
      </div>
      <div class="scroll-item">
          <div class="part-title">量级控制</div>
      </div>
      <div class="scroll-item">
          <div class="part-title">新计划管理</div>
      </div>
      <div class="scroll-item">
          <div class="part-title">老计划管理</div>
      </div>
      <div class="scroll-item">
          <div class="part-title">垃圾计划清理</div>
      </div>
    </div>
    
  </div>
</template>
<script>
export default {
    data() {
        return {
            activeStep: 0,
            partList: ['基本信息', '风险控制', '成本控制', '量级控制', '新计划管理', '老计划管理', '垃圾计划清理']
        }
    },
    methods: {
        // 滚动触发按钮高亮
        onScroll (e) {
            let scrollItems = document.querySelectorAll('.scroll-item')
            for (let i = scrollItems.length - 1; i >= 0; i--) {
                // 判断滚动条滚动距离是否大于当前滚动项可滚动距离
                let judge = e.target.scrollTop >= scrollItems[i].offsetTop - scrollItems[0].offsetTop - 100;
                if (judge) {
                    this.activeStep = i
                    break
                }
            }
        },
        // 点击切换锚点
        jump (index) {
            let target = document.querySelector('.scroll-content')
            let scrollItems = document.querySelectorAll('.scroll-item')
            // 判断滚动条是否滚动到底部
            if (target.scrollHeight <= target.scrollTop + target.clientHeight) {
                this.activeStep = index
            }
            let total = scrollItems[index].offsetTop - scrollItems[0].offsetTop // 锚点元素距离其offsetParent(这里是body)顶部的距离(待滚动的距离)
            let distance = document.querySelector('.scroll-content').scrollTop // 滚动条距离滚动区域顶部的距离
            // let distance = document.body.scrollTop || document.documentElement.scrollTop || window.pageYOffset // 滚动条距离滚动区域顶部的距离(滚动区域为窗口)
            // 滚动动画实现, 使用setTimeout的递归实现平滑滚动,将距离细分为50小段,10ms滚动一次
            // 计算每一小段的距离
            let step = total / 50
            if (total > distance) {
                smoothDown(document.querySelector('.scroll-content'))
            } else {
                let newTotal = distance - total
                step = newTotal / 50
                smoothUp(document.querySelector('.scroll-content'))
            }
            // 参数element为滚动区域
            function smoothDown (element) {
                if (distance < total) {
                    distance += step
                    element.scrollTop = distance
                    setTimeout(smoothDown.bind(this, element), 1)
                } else {
                    element.scrollTop = total
                }
            }
            // 参数element为滚动区域
            function smoothUp (element) {
                if (distance > total) {
                    distance -= step
                    element.scrollTop = distance
                    setTimeout(smoothUp.bind(this, element), 1)
                } else {
                    element.scrollTop = total
                }
            }
            // document.querySelectorAll('.scroll-item').forEach((item, index1) => {
            //   if (index === index1) {
            //     item.scrollIntoView({
            //       block: 'start',
            //       behavior: 'smooth'
            //     })
            //   }
            // })
        }
    }
}
</script>
<style lang="scss" scoped>
  .auto-adjust-edit {
    flex-basis: 100%;
    display: flex;
    overflow: hidden;
    height: 500px;
    height: 100%;
    // 侧边栏
    .operation-btn {
        width: 9.5%;
        height: 95%;
        margin-right: 0.5%;
        padding-top: 1%;
        margin-top: 4px;
        background: white;
        border: 1px solid rgb(190, 188, 188);
        border-radius: 6px;
        box-shadow: 0 3px 12px 0 rgba(0, 0, 0, 0.2);
        .btn-item {
            height: 40px;
            line-height: 40px;
            padding-left: 20px;
            cursor: pointer;
        }
    }
    // 表单内容
    .scroll-content {
        height: 100%;
        width: 90%;
        overflow: auto;
        .scroll-item {
            background: white;
            border-radius: 8px;
            margin-bottom: 6px;
            border: 1px solid rgb(216, 214, 214);
            min-height: 300px;
            // 标题
            .part-title {
                height: 40px;
                line-height: 40px;
                font-weight: 600;
                padding-left: 10px;
            }
            // 表单
            /deep/.el-form {
                border: 1px solid rgb(190, 189, 189);
                width: 98%;
                margin: 10px auto 30px;
                border-radius: 6px;
                /deep/.el-form-item {
                margin-bottom: 12px;
                margin-top: 10px;
                }
            }
        }
    }
  }
</style>

以上为个人经验,希望能给大家一个参考,也希望大家多多支持阿兔在线工具。

点赞(0)

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部