vant 2:van-tabs组件标签切换时滚动位置不准的问题

文章描述了一个在使用van-tabs组件时遇到的标签不居中且滚动位置异常的问题。作者通过查看源码,定位到scrollIntoView方法中的问题,并提出了一个补丁解决方案,即重写scrollIntoView方法,直接设置容器的scrollLeft来实现标签居中。在main.js中引入这个补丁,成功修复了问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

按照官网描述,标签超过swipe-threshold的值(默认5)的时候,会把当前选中标签居中

 

项目中使用van-tabs组件时发现有以下问题,当前选中的标签并没有居中,并且横向滚动的位置也很奇怪。

 

查看van-tabs源码:

// vant/lib/tabs/index.js
watch: {
    ...
    currentIndex: function currentIndex() {
      this.scrollIntoView();
      this.setLine(); // scroll to correct position
 
      if (this.stickyFixed && !this.scrollspy) {
        (0, _scroll.setRootScrollTop)(Math.ceil((0, _scroll.getElementTop)(this.$el) - this.offsetTopPx));
      }
    },
    ...
  },
methods: {
    // scroll active tab into view
    scrollIntoView: function scrollIntoView(immediate) {
      var titles = this.$refs.titles;
 
      if (!this.scrollable || !titles || !titles[this.currentIndex]) {
        return;
      }
 
      var nav = this.$refs.nav;
      var title = titles[this.currentIndex].$el;
      var to = title.offsetLeft - (nav.offsetWidth - title.offsetWidth) / 2;
      (0, _utils2.scrollLeftTo)(nav, to, immediate ? 0 : +this.duration);
    },
}
 
// ./utils2
function scrollLeftTo(scroller, to, duration) {
  var count = 0;
  var from = scroller.scrollLeft;
  var frames = duration === 0 ? 1 : Math.round(duration * 1000 / 16);
 
  function animate() {
    scroller.scrollLeft += (to - from) / frames;
    // 主要是这里滚动的值有问题,但原因暂未搞清楚
    if (++count < frames) {
      (0, _raf.raf)(animate);
    }
  }
 
  animate();
}

处理方案:虽然还没搞清楚是什么原因导致的bug,但是可以定位到具体哪几行代码的问题,最直接的打补丁重写scrollLeftTo方法即可 

// 创建src/patches/van-tabs.js
 
import { Tabs } from 'vant'
 
const TabsPatched = {
    extends: Tabs,
    methods: {
        // scroll active tab into view
        scrollIntoView: function scrollIntoView(immediate) {
            var titles = this.$refs.titles;
     
            if (!this.scrollable || !titles || !titles[this.currentIndex]) {
                return;
            }
 
            var nav = this.$refs.nav;
            var title = titles[this.currentIndex].$el;
            var to = title.offsetLeft - (nav.offsetWidth - title.offsetWidth) / 2;

            // 注释原来的scrollLeftTo方法,直接设置容器的scrollLeft将当前选中的标签滚动至居中位置
            // (0, _utils2.scrollLeftTo)(nav, to, immediate ? 0 : +this.duration);
             
            setTimeout(_ => {
                nav.scrollLeft += to - nav.scrollLeft
            }, immediate ? 0 : this.duration * 1000)
        },
    }
}
 
export default {
    install(Vue) {
        Vue.component(Tabs.name, TabsPatched)
    }
}
 
// 在main.js引入替换原来的tabs组件
 
import Vue from 'vue'
import TabsPatched from '@/patches/van-tabs'
 
Vue.use(TabsPatched)

 补丁修复后:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值