前天,一个同事像我咨询一个问题:
“hi, shunzi,你弄过vux中的那种range没有,但是比那个要复杂一点,需要支持左右两边滑,取中间的区间值?”
“没有呢”
“啊,我们有这样一个需求,需要支持左右滑动,取区间,我改vux的range改得有bug哇,你能不能帮我看看,或者封装一个”
“给你个眼神自己体会,刚好我现在不是很忙,可以看看”
“好的,麻烦你了,到时请你吃饭哇”

背景

背景需求大概就是这样,需要一个vue的插件,支持左右滑动,取他的区间值,vux的range,最开始,我也准备改造一下这个插件,发现自己太渣了,改了半天,事件绑定都乱套了,就自己写一个算了。

image

思路讲解

  • 插件其实就好比在一个管道里,有两个小球,两个小球,在获取焦点的时候,能够左右滑动
  • 在管道长度固定的情况下(100%),
    • 左边的小球不可能滚到右边小球的右边,右边小球不能滚到左边小球的左边,临界点在于他们相碰
    • 左边小球相对管道左端距离的百分比(left)乘以管道的总长(maxNumber-minNumber),就是最小值【min】
    • 右边小球相对管道右端距离的百分比(right)乘以管道的总长(maxNumber-minNumber),就是球距右端的距离,然后用管长减去这个距离(maxNumber-minNumber)*(1-right)就是【max】

- 最后取得的min/max,有可能是小数,那么,我们应该还要支持用户自定义保留几位小数【pointLen】

image

核心代码展示

# 父组件
<div class="contanier">
    <vueRange :min-num="0" :max-num="5000" point-len="0"/>
</div>

components: {
'vueRange': () =>
  import ('@/component/vue_range/range.vue'),
},

# 子组件
export default {
  props: {
    minNum: "",
    maxNum: "",
    pointLen: 0
  },
  data() {
    return {
      minNumber: this.minNum || 0, //最小值
      maxNumber: this.maxNum || 100, //最大值
      _width: 0, //屏幕的宽度
      dist: 0, //矫正系数
      left: 0, //handle min 的left偏移量
      right: 0, //handle max 的right偏移量
    };
  },
  mounted() {
    this._width = this.$refs.bar.clientWidth
    this.dist = this.$refs.min.clientWidth / this._width * 100
  },
  methods: {
    move(event, type) {
      var _left = (event.targetTouches[0].clientX - 10) / this._width * 100;
      if (type == 'min') {
        // 当前最小值不能大于最大值,且不能小于0
        if ((_left + this.right) > 100 || _left < 0) {
          return;
        } else {
          this.left = _left;
        }
      } else {
        // 当前最大值不能小于最小值,且不能大于100
        if (this.left > _left || _left >= 100) {
          return;
        } else {
          this.right = 100 - _left;
        }
      }
    },
  },
  computed: {
    min() {
      return ((this.maxNumber - this.minNumber) * this.left / 100).toFixed(this.pointLen);
    },
    max() {
      return ((this.maxNumber - this.minNumber) * (100 - this.right) / 100).toFixed(this.pointLen);
    }
  }
}

待优化

  • 在区间很大的情况下,左右小球滑动到一起,虽然不能在向中间靠拢,但是最小值并不等于最大值
  • 在手机上面,小球获取焦点,不是那么顺畅,有时感觉按不住
  • 实际中,最后计算出的最大值、最小值,应该传值到父组件中,这个暂时没有涉及,如果需要,可以传递一个方法,在这个组件中,对min/max进行计算,只要一个发生改变,就emit这个方法,然后在父组件中接收

参考

vux的Range
vux的Range源码
源码地址
更多精彩,请关注订阅号韶华随记

ps: 如果你也有一些搞不定的小需求,可以联系我,如果时间允许,我也是很乐意能帮助到你(微信号与昵称相同)。当然,如果你不想让我死宅在家里,可以面个基or吃个饭or喝个茶,当然最好是给我介绍个女朋友

Logo

前往低代码交流专区

更多推荐