vue可滑动的tab组件使用详解

本文实例为大家分享了vue可滑动tab组件使用的具体代码,供大家参考,具体内容如下

需求:

1. 每个tab-item的间距是相同的,可定制

2. 每一个tab-item的宽度是随着文字的增多而宽度增大

3. 当tab-item小于等于4个时,tab-item填满当前屏幕,平分剩余空间;当tab-item超过4个时,tab可滑动选择

4. 点击tab-item时,底部横线居中显示,跟随在点击的tab-item底部

5. 从上一个页面点击一级分类,进入此页面,显示上一页面点击的一级分类名称,居中显示,样式高亮

先展示效果截图

前期知识点

1)offsetLeft:子元素相对于父元素最左上角侧的横向偏离位置

2)offsetWidth: 元素的宽度

3)scrollLeft: 滑动到对应的x坐标

4)定位元素style.left的运用

5)vux组件之滑动tab的运用 (需要用到组件自带的onItemClick()方法,通过dom,可以起到点击该tab-item的作用)

难点

1)使用vux的可滑动的tab,修改组件css,如何令到每一个tab的间距为响应式的。

原本vux的可滑动的tab是根据scrollWidth的长度来自动计算每一个tab-item的宽度的,因为包含这tab-item的tabBox这个div使用的是flex布局,而tab-item是它的子元素,它会自动沾满tabBox。如果文字超出了tab-item的宽度,文字就会被隐藏。

可以通过修改vux-tab-item这个样式来自定义样式,把子元素的弹性属性去除,并且设置他的padding,这样可以呈现出文字能显示全,并且每个tab-item间距相同的效果,css如下:

/*改变原来tabBox的flex布局*/
.mpm-container .vux-tab .vux-tab-item {
  display: inline-block;
  width: auto;
  height: 100%;
  padding: 0 10px;
  flex: none;
  background: transparent;
  overflow: hidden;
}

2)这个组件最核心之一的就是底部bar的精准定位跟随

因为上面的1)改变了布局,所以导致底部bar跟随不准确的情况,我们可以定制bar。在vux里面,bar是一个div,它有滑动的动画,我的做法是这样的,首先通过right让它置于tab的最左侧,然后通过按钮点击事件获得相对应的tab-item元素的下标,然后使用for循环从第一tab-item开始寻找,如果不为改元素,则把它的元素宽度进行累加,直到找到该需激活的tab-item,然后通过数学计算可把bar定位在该元素的底部并且居中,代码如下:

onItemClick(keyword, index) {
      let barLeft = 0;
      document.getElementsByClassName('vux-tab-ink-bar')[0].style.right = '100%';
      for (let i = 0; i < this.list.length; i++) {
        if (document.getElementsByClassName('vux-tab-item')[i].innerText === keyword) {
          barLeft += document.getElementsByClassName('vux-tab-item')[i].offsetWidth / 2;
          //为什么是15?因为底部bar长度为30px,这样做可以让bar的中心对齐tab-item的中心
          barLeft -= 15;
          break;
        }
        barLeft += document.getElementsByClassName('vux-tab-item')[i].offsetWidth;
      }
      document.getElementsByClassName('vux-tab-ink-bar')[0].style.left = (barLeft + 'px');
    },

3)从前一个页面点击一级分类进入商品列表页,自动选中并在屏幕居中显示被选中的tab-item

当超出手机的可视宽度时,获取当前屏幕宽度,然后评分长度,计算之后,平均分给tab-item,因为每一个tab-item自己的样式中有设置的padding属性,所以间距相同,不需要额外为间距分配空间。

否则则不需要分配宽度,因为是flex布局的子元素,每一个tab-item会根据自己的文字得到自己的宽度。

附完整代码:

<template>
  <div class="mpm-container">
    <div style="width: 100%;overflow:scroll; -webkit-overflow-scrolling:touch;">
      <tab ref="tabBox" bar-active-color="#149c81" active-color="#149c81" :line-width="4" :custom-bar-width="getBarWidth" v-model="tabD" :style="{width: tabWidth + 'px'}">
        <tab-item v-for="(item,index) in list" :key="index" @on-item-click="onItemClick(item, index)">{{item}}
        </tab-item>
      </tab>
    </div>
  </div>
</template>
 
<script>
import {
  Tab, TabItem
} from 'vux';
 
export default {
  data() {
    return {
      list: ['打印机', '订书机11111111', '订书机5', '打印机333333', '复读机333333',],
      tabD: 0,
      // tab标签div长度
      tabWidth: document.body.clientWidth,
    }
  },
  computed: {},
  components: {
    Tab, TabItem
  },
  mounted() {
    setTimeout(() => {
      this.$refs.tabBox.$children[0].onItemClick();
    }, 200)
    this.setTabWidth();
  },
  methods: {
    setTabWidth() {
      // 页面完成刷新之后
      this.$nextTick(() => {
        var realW = 0, offW = 0;
        // realW为每一个tab-item的长度总和,因为tab-item的父级为flex布局,而tab-item的flex: none,所以初始化的时候,tab-item会根据自己的字体长度,自动扩张宽度。
        for (let i = 0; i < this.$refs.tabBox.$children.length; i++) {
          realW += this.$refs.tabBox.$children[i].$el.offsetWidth;
        }
        // 同样是计算初始化的时候,每一个tab-item的总宽度,但当tab-item总长度大于tab的总长度时,立马退出程序
        for (let i = 0; i < this.$refs.tabBox.$children.length; i++) {
          offW += this.$refs.tabBox.$children[i].$el.offsetWidth;
          if (offW > (document.body.clientWidth)) break
        }
        // 假如tab-item的总宽度小于显示tabwidth,则评分tab的剩余空间,加到每一个tab-item中
        if (offW < (document.body.clientWidth)) {
          var offD = (document.body.clientWidth) - offW;
          for (let i = 0; i < this.$refs.tabBox.$children.length; i++) {
            this.$refs.tabBox.$children[i].$el.style.width = this.$refs.tabBox.$children[i].$el.clientWidth + offD / this.$refs.tabBox.$children.length + 'px';
          }
        } else {
          this.tabWidth = realW;
        }
      })
    },
    getBarWidth() {
      // 函数控制tab-bar的宽度,如果tab标签页数量为1,则隐藏tab-bar
      if (this.list && this.list.length === 1) {
        return '0px';
      }
      return '30px';
    },
    onItemClick(keyword, index) {
      let barLeft = 0;
      document.getElementsByClassName('vux-tab-ink-bar')[0].style.right = '100%';
      for (let i = 0; i < this.list.length; i++) {
        if (document.getElementsByClassName('vux-tab-item')[i].innerText === keyword) {
          barLeft += document.getElementsByClassName('vux-tab-item')[i].offsetWidth / 2;
          //为什么是15?因为底部bar长度为30px,这样做可以让bar的中心对齐tab-item的中心
          barLeft -= 15;
          break;
        }
        barLeft += document.getElementsByClassName('vux-tab-item')[i].offsetWidth;
      }
      document.getElementsByClassName('vux-tab-ink-bar')[0].style.left = (barLeft + 'px');
    },
 
  }
}
 
</script>
 
<style scoped lang="less">
/*改变原来tabBox的flex布局*/
.mpm-container .vux-tab .vux-tab-item {
  display: inline-block;
  width: auto;
  height: 100%;
  padding: 0 10px;
  flex: none;
  background: transparent;
  overflow: hidden;
}
</style>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Vue实现tab导航栏并支持左右滑动功能

    本文主要介绍:利用Vue实现tab导航栏,并且通过flex布局实现左右滑动,计算按钮的位置,当点击第一屏展示的最后一个且还有元素未展示时,自动滑动显示出未显示的元素. tab导航栏布局: <section class="theme-list"> <div class="fixed-nav" ref="fixednav"> <div class="fixed-nav-content"> <

  • 写一个移动端惯性滑动&回弹Vue导航栏组件 ly-tab

    前段时间写了一个移动端的自适应滑动Vue导航栏组件,觉得有一定实用性,大家可能会用得到(当然有些大佬自己写得更好的话就没必要啦),于是前两天整理了一下,目前已经发布到npm和GitHub上了,点我到npm,点我到GitHub项目 ,有需要的同学可以在项目中 npm install ly-tab -S 或者 yarn add ly-tab 使用,具体用法下面会讲到. 好了,先看看效果吧 好的,开始废话了,实习差不多3个月了,这段时间跟着导师大佬也有接触过一些项目,也学到了不少东西,接触到的项目基本

  • vue实现鼠标滑动展示tab栏切换

    本文实例为大家分享了vue实现鼠标滑动展示tab栏切换的具体代码,供大家参考,具体内容如下 动画效果: 代码如下: <template>   <div id="header">     <div class="conten_width">       <div class="contnet_width_content">         <div style="    transfo

  • vue可滑动的tab组件使用详解

    本文实例为大家分享了vue可滑动tab组件使用的具体代码,供大家参考,具体内容如下 需求: 1. 每个tab-item的间距是相同的,可定制 2. 每一个tab-item的宽度是随着文字的增多而宽度增大 3. 当tab-item小于等于4个时,tab-item填满当前屏幕,平分剩余空间:当tab-item超过4个时,tab可滑动选择 4. 点击tab-item时,底部横线居中显示,跟随在点击的tab-item底部 5. 从上一个页面点击一级分类,进入此页面,显示上一页面点击的一级分类名称,居中显

  • vue+elementUi图片上传组件使用详解

    上传组件封装需求分析 在基于elementUI库做的商城后台管理中,需求最大的是商品管理表单这块,因为需要录入各种各样的商品图片信息.加上后台要求要传递小于2M的图片,因此封装了一个upload.vue组件作为上传页面的子组件,它用于管理图片上传逻辑. upload.vue解析 upload主要用于实现表单上传图片的需求,主要由input +img 构成当没有图片的时候显示默认图片,有图片则显示上传图片,因为input样式不太符合需求所以只是将起设置为不可见,不能将其设置为display:non

  • 微信小程序可滑动周日历组件使用详解

    微信小程序可滑动周日历组件,供大家参考,具体内容如下 看网上周日历组件比较少,自己弄了一个,和大家分享一下. 如果样式变形,请检查是否有共用样式起冲突 展示一下效果图 在components组件文件夹下新建calendarWeek文件夹 直接上代码吧: index.wxml <!--components/calendarWeek/index.wxml--> <!-- 日历 --> <view class="date-choose shrink border-bott

  • 微信小程序可滑动月日历组件使用详解

    微信小程序可滑动月日历组件 此日历可进行左右滑动,展示签到打卡信息,和大家分享一下. 如果样式变形,请检查是否有共用样式起冲突 展示一下效果图 在components组件文件夹下新建calendarMonth文件夹 直接上代码吧: index.wxml <!--components/calendar/index.wxml--> <view class='month'> <!-- <view class='arrow' bindtap='prevMonth'><

  • Vue按时间段查询数据组件使用详解

    本文实例为大家分享了Vue按时间段查询数据组件的具体使用代码,供大家参考,具体内容如下 首先是前端效果: 界面代码如下: <template> <a-col :md="6" :sm="10"> <a-form-item label="执行时间" :labelCol="labelCol" :wrapperCol="wrapperCol"> <a-range-picke

  • vue更多筛选项小组件使用详解

    本文实例为大家分享了vue更多筛选项小组件的实现方法,供大家参考,具体内容如下 效果: 就是一个简单的小效果,当有很多筛选条件时,默认只展示几项,不会觉得很冗余,有需要可以点击展开,进行更过的条件筛选.并且能够自动判断界面的尺寸,决定是否需要更多筛选项.直接把"查询.重置"内置到组件里面了,便于组件样式的实现,还可以进行插槽. 正常大屏 分辨率变小 可见出现了更多筛选的按钮,可以点击下拉 插槽 代码: <template> <div :class="['co

  • vue悬浮表单复合组件开发详解

    本文实例为大家分享了vue悬浮表单复合组件开发的具体代码,供大家参考,具体内容如下 组件样式 组件功能 卡片形式展示筛选条件点击添加筛选后展示悬浮表单表单内完成条件选择后点击保存,新增一个卡片 开发 <div class="form-label">筛选条件:</div> <template v-for="(item, index) in fitter">   <div :key="index" class

  • 使用Vue制作图片轮播组件思路详解

    之前一直都没有认真的写过一个组件.以前在写业务代码的过程中,都是用的别人封装好的组件,这次尝试着写了一个图片轮播组件,虽然比不上知名的轮播组件,但它的功能基本完整,而且在写这个组件的过程中,学的东西也很多,在这里也给大家分享出来,如有疏漏,欢迎指正! 在制作这个组件之前,笔者google了不少关于轮播的文章,发现实现一个轮播的思路虽然各有不同,但是大的逻辑其实差不多,本文主要依据慕课网上焦点轮播图特效这节课,不过慕课网主要用原生JS写,而笔者则用Vue进行了重构,并且进行了一点修改.完成后的组件

  • vue远程加载sfc组件思路详解

    问题 在我们的 vue 项目中(特别是后台系统),总会出现一些需要多业务线共同开发同一个项目的场景,如果各业务团队向项目中提供一些公共业务组件,但是这些组件并不能和项目一起打包,因为项目中不能因为某个私有模块的频繁变更而重复构建发布. ^_^不建议在生产环境使用,代码包含eval 思路 在这种场景下我们需要将公共的业务组件部署到服务端,由客户端请求并渲染组件. 服务端解析.vue文件 使用vue-template-compiler 模板解析器,解析SFC(单文件组件) const compile

  • vue实现鼠标滑动预览视频封面组件示例详解

    目录 组件效果 组件设计 1.视频截取关键帧 2.鼠标移入封面时显示对应关键帧 3.视频和封面的状态切换 功能实现 1.视频截取关键帧图片列表 1.1 截取指定帧 1.2 截取stepNums张关键帧图片 2.鼠标移入封面时显示对应关键帧 2.1 鼠标移动事件监听 2.2 鼠标移出事件监听 3.视频和封面的状态切换 3.1 播放视频 3.2 视频暂停 组件使用 组件库引用 组件效果 https://www.jb51.net/Special/926.htm 组件设计 我们首先应该要对组件进行一个简

随机推荐