【Vue】Element滑块Slider自定义提示Tooltip(tooltip保持常显)

2,723 阅读1分钟

客户要求值要始终显示,但Element滑块用的是自身的Tooltip组件, element-ui并没有提供常显的功能。

其源码如下:

<!-- 省略了一些属性:<div ...> --> <div> <el-tooltip placement="top" ref="tooltip" :popper-class="tooltipClass" :disabled="!showTooltip"> <span slot="content">{{ formatValue }}</span> <div class="el-slider__button" :class="{ 'hover': hovering, 'dragging': dragging }"></div> </el-tooltip> </div>

Tooltip的触发机制是鼠标事件,只有鼠标移动到对应的元素上时才创建Tooltip,该行为不符合客户需求。

Element文档中描述,可以通过show-tooltip来禁用默认的Tooltip,并可以通过input事件来实时同步改变的数据。

同时通过页面审查元素,发现滑动点是通过left属性完成位移的,同时通过translateX来完成元素向左偏移一半。

如代码所示:

<style>
  .el-slider__button-wrapper {
    /** ... */
    ransform: translateX(-50%);
  }
</style>
<div
  tabindex="0"
  class="el-slider__button-wrapper"
  style="left: 45%;">
  <!-- ... -->
</div>

封装一个自己的slider

我们可以基于分析的几点来实现自定义的Tooltip。定义一个MySlider.vue组件:

<template>
  <div class="my-slider">
    <div class="my-slider__tooltip" :style="style">
      <el-button
        class="my-slider__tooltip-wrapper"
        size="mini"
      >
        {{ slider }}
      </el-button>
    </div>
    <el-slider
      v-model="slider"
      :format-tooltip="(value) => `${value}${unit}`"
      :show-tooltip="false"
      :min="min"
      :max="max"
      @input="input"
    ></el-slider>
  </div>
</template>

<script>
export default {
  name: 'MySlider',
  model: {
    prop: 'value',
    event: 'change',
  },
  props: {
    value: {
      type: Number,
      default: 100,
    },
    min: {
      type: Number,
      default: 0,
    },
    max: {
      type: Number,
      default: 100,
    },
  },
  data() {
    return {
      slider: this.value,
    }
  },
  watch: {
    value(newValue) {
      this.slider = newValue
    },
  },
  computed: {
    style() {
      const length = this.max - this.min,
        progress = this.slider - this.min,
        left = progress / length * 100
      return {
        paddingLeft: `${left}%`,
      }
    },
  },
  methods: {
    input(value) {
      this.$emit('change', value)
    },
  },
}
</script>

<style lang="scss" scoped>
.my-slider {
  .my-slider__tooltip {
    text-align: left;
    .my-slider__tooltip-wrapper {
      height: 32px;
      transform: translateX(-50%);
      top: -50%;
    }
  }
}
</style>

引入并使用它:

<template>
    <my-slider v-model="luminosity"></my-slider>
</template>
<script>
import MySlider from '@/components/MySlider'

export default {
  name: 'MyController',
  components: {
    MySlider,
  },
  data() {
    return {
      luminosity: 50,
    }
  },
}
</script>