分析
客户要求值要始终显示,但Element滑块用的是自身的Tooltip组件。
其源码如下:
<!-- 省略了一些属性:<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>
组件化
我们可以基于分析的几点来实现自定义的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>