vue锚点定位中tab高亮错误

168 阅读2分钟

最近出现了一个 tab 定位出错的问题,纠结了很久也没改好,但记录一下 tab 滑动定位怎么实现,以及这个问题是啥。

功能:一个弹框,左边一个 el-tab,记录标题,右边对应几个 div,和左边对应。点击左边 tab 的时候,右边滑到相应位置;右边滑动的时候,根据位置,左边的 tab 激活状态也要改变。

但现在的问题是,当最后几个 div 高度较小,基本处在同一屏的时候,会出现左边 tab 定位不准。比如我点了tab0 -> tab2,这个时候即使 scrollIntoView 设置为 start 了,div2 也没法置顶(它的高度不足以填充整个父容器),然后 tab 点击事件改变 activeTab 为 tab2,滑动事件又判断 activeTab 为 tab0,最后就导致这个 tab 没法切到 tab2,无论怎么点都是 tab0。

image-24.png

这个组件的封装如下:

<template>
<div :style="{ display:flex }">
<el-tab @tab-click="handleTabClick">这里循环</el-tab>
<div @scroll="handleContentScroll">这里循环</div>
</div>
</template>

<script>
updated() {
  this.$nextTick(()=>{
    setTimeout(() => {
      this.tabs.forEach((item) => {
        //按照tab依次获取dom
        const dom = this.handleDom(item);
        if (this.value && dom) {
          //确定每一个div块相较于父元素的位置,以及自己的高度。此处注意:https://blog.csdn.net/shibazijiang/article/details/103894498
          this.handleOffsetTop(dom, item);
        }
      });
    }, 200);
  })
},

// tab点击滑动
handleTabClick({ name, spillOverValue }) {
  //先按className获取对应div
  const tabContentPropHTMLCollection = document.getElementById(`dialog_${this.dialogId}`).getElementsByClassName(`nb-scroll-tabs__${name}`)
  let element;
  if(tabContentPropHTMLCollection.length) {
    element = tabContentPropHTMLCollection[0]
  }
  //滑动到最上面
  element?.scrollIntoView({
    block: 'start',
    behavior: 'smooth' // smooth instant
  })
  //修改activeTab
  this.$emit("tab-click", name);
  this.$emit("update:activeTab", name);
},

//滑动监听tab的改变
handleContentScroll(e) {
  const currentScrollTop = e.target.scrollTop;
  Object.keys(this.offsetTops).forEach((key) => {
    const item = this.offsetTops[key];
    if (
      currentScrollTop + 34 >= item.offsetTop &&
      currentScrollTop + 34 < item.offsetTop + item.height
    ) {
      //判断目前的滑动距离和div的offsetTop之间的关系,修改activeTab
      this.$emit("update:activeTab", key);
    }
  });
},
</script>

然后现在出问题的地方就在:handleTabClick更改activeTab为tab2,但handleContentScroll判断目前的activeTab还是tab0,怎么点都切不到tab2,彻底疯狂!!

最后加了一个延时,让handleTabClick的activeTab触发在handleContentScroll之后,这样可以保证最后的tab激活状态是正确的,但页面效果会时不时出现四处乱跳的情况,用一个bug代替了另一个bug,我是懂拆东墙补西墙的:

handleTabClick({ name, spillOverValue }) {
  const tabContentPropHTMLCollection = document.getElementById(`dialog_${this.dialogId}`).getElementsByClassName(`nb-scroll-tabs__${name}`)
  let element;
  if(tabContentPropHTMLCollection.length) {
    element = tabContentPropHTMLCollection[0]
  }
  element?.scrollIntoView({
    block: 'start',
    behavior: 'smooth'
  })

//怎么不算解决了呢.jpg
  setTimeout(()=>{this.$emit("tab-click", name);
  this.$emit("update:activeTab", name);}, 600)
},

scrollIntoView:developer.mozilla.org/zh-CN/docs/… scrollIntoView会尝试将元素滚动到可见区域的顶端。在这种情况下,"可见区域的顶端" 指的是包含元素的父容器(通常是某个滚动的容器)的顶端。如果父容器本身也是一个滚动容器,那么它将滚动到该容器的顶端。