当前位置:   article > 正文

vue 可滑动的tab组件----vux插件tab的使用_vue-router-tab页面滚动元素如何使用

vue-router-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如下:

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

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

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

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

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

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

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

附完整代码:

  1. <template>
  2. <div class="mpm-container">
  3. <div style="width: 100%;overflow:scroll; -webkit-overflow-scrolling:touch;">
  4. <tab ref="tabBox" bar-active-color="#149c81" active-color="#149c81" :line-width="4" :custom-bar-width="getBarWidth" v-model="tabD" :style="{width: tabWidth + 'px'}">
  5. <tab-item v-for="(item,index) in list" :key="index" @on-item-click="onItemClick(item, index)">{{item}}
  6. </tab-item>
  7. </tab>
  8. </div>
  9. </div>
  10. </template>
  11. <script>
  12. import {
  13. Tab, TabItem
  14. } from 'vux';
  15. export default {
  16. data() {
  17. return {
  18. list: ['打印机', '订书机11111111', '订书机5', '打印机333333', '复读机333333',],
  19. tabD: 0,
  20. // tab标签div长度
  21. tabWidth: document.body.clientWidth,
  22. }
  23. },
  24. computed: {},
  25. components: {
  26. Tab, TabItem
  27. },
  28. mounted() {
  29. setTimeout(() => {
  30. this.$refs.tabBox.$children[0].onItemClick();
  31. }, 200)
  32. this.setTabWidth();
  33. },
  34. methods: {
  35. setTabWidth() {
  36. // 页面完成刷新之后
  37. this.$nextTick(() => {
  38. var realW = 0, offW = 0;
  39. // realW为每一个tab-item的长度总和,因为tab-item的父级为flex布局,而tab-item的flex: none,所以初始化的时候,tab-item会根据自己的字体长度,自动扩张宽度。
  40. for (let i = 0; i < this.$refs.tabBox.$children.length; i++) {
  41. realW += this.$refs.tabBox.$children[i].$el.offsetWidth;
  42. }
  43. // 同样是计算初始化的时候,每一个tab-item的总宽度,但当tab-item总长度大于tab的总长度时,立马退出程序
  44. for (let i = 0; i < this.$refs.tabBox.$children.length; i++) {
  45. offW += this.$refs.tabBox.$children[i].$el.offsetWidth;
  46. if (offW > (document.body.clientWidth)) break
  47. }
  48. // 假如tab-item的总宽度小于显示tabwidth,则评分tab的剩余空间,加到每一个tab-item中
  49. if (offW < (document.body.clientWidth)) {
  50. var offD = (document.body.clientWidth) - offW;
  51. for (let i = 0; i < this.$refs.tabBox.$children.length; i++) {
  52. this.$refs.tabBox.$children[i].$el.style.width = this.$refs.tabBox.$children[i].$el.clientWidth + offD / this.$refs.tabBox.$children.length + 'px';
  53. }
  54. } else {
  55. this.tabWidth = realW;
  56. }
  57. })
  58. },
  59. getBarWidth() {
  60. // 函数控制tab-bar的宽度,如果tab标签页数量为1,则隐藏tab-bar
  61. if (this.list && this.list.length === 1) {
  62. return '0px';
  63. }
  64. return '30px';
  65. },
  66. onItemClick(keyword, index) {
  67. let barLeft = 0;
  68. document.getElementsByClassName('vux-tab-ink-bar')[0].style.right = '100%';
  69. for (let i = 0; i < this.list.length; i++) {
  70. if (document.getElementsByClassName('vux-tab-item')[i].innerText === keyword) {
  71. barLeft += document.getElementsByClassName('vux-tab-item')[i].offsetWidth / 2;
  72. //为什么是15?因为底部bar长度为30px,这样做可以让bar的中心对齐tab-item的中心
  73. barLeft -= 15;
  74. break;
  75. }
  76. barLeft += document.getElementsByClassName('vux-tab-item')[i].offsetWidth;
  77. }
  78. document.getElementsByClassName('vux-tab-ink-bar')[0].style.left = (barLeft + 'px');
  79. },
  80. }
  81. }
  82. </script>
  83. <style scoped lang="less">
  84. /*改变原来tabBox的flex布局*/
  85. .mpm-container .vux-tab .vux-tab-item {
  86. display: inline-block;
  87. width: auto;
  88. height: 100%;
  89. padding: 0 10px;
  90. flex: none;
  91. background: transparent;
  92. overflow: hidden;
  93. }
  94. </style>

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/76942
推荐阅读
相关标签
  

闽ICP备14008679号