Slider 滑块
在连续区间内取值,比数字输入框更直观。支持横向与纵向两种布局,拖动过程通过 requestAnimationFrame 合帧(每帧最多抛一次),松手或键盘调节时才提交最终值。轨道粗细与拇指直径既可由 size 预设整体缩放,也能用 trackSize / thumbSize 单独覆盖。
代码演示
基础用法
v-model 绑定数值,min / max / step 描述取值范围。拖动过程中 update:modelValue 持续更新,松手时抛一次 change。
change 的参数是拖动结束时的最终值。
<script setup lang="ts">
import { ref } from 'vue'
const value = ref(40)
const committed = ref(40)
function onChange(next: number) {
committed.value = next
}
</script>
<template>
<div class="m-row-demo--stretch">
<MSlider v-model="value" :min="0" :max="100" :step="1" @change="onChange" />
<span>拖动中:{{ value }},松手后(change):{{ committed }}</span>
</div>
</template>纵向布局
vertical 后轨道自上而下、最小值在底部。组件自身高度是 100%,必须由父容器给出高度,否则会塌陷。
父容器 height: 160px,三个纵向滑块共享同一高度。
<script setup lang="ts">
import { ref } from 'vue'
const volume = ref(70)
const brightness = ref(45)
const zoom = ref(20)
</script>
<template>
<div class="m-row-demo" style="align-items: flex-end">
<div style="height: 160px; display: flex; gap: 28px">
<MSlider v-model="volume" vertical color="primary" />
<MSlider v-model="brightness" vertical color="warning" />
<MSlider v-model="zoom" vertical color="info" />
</div>
<span>音量 {{ volume }} / 亮度 {{ brightness }} / 缩放 {{ zoom }}</span>
</div>
</template>尺寸与尺寸覆盖
size 三档整体等比缩放(small 0.75×、large 1.5×)。trackSize / thumbSize 以 px 覆盖对应部分,优先级高于 size。
后两条分别只改轨道(细线型)和只改拇指(大触摸目标)。
<script setup lang="ts">
import { ref } from 'vue'
const small = ref(30)
const normal = ref(50)
const large = ref(70)
const thinRail = ref(60)
const fatThumb = ref(40)
</script>
<template>
<div class="m-row-demo--stretch">
<MSlider v-model="small" size="small" />
<MSlider v-model="normal" size="default" />
<MSlider v-model="large" size="large" />
<MSlider v-model="thinRail" :track-size="2" :thumb-size="10" />
<MSlider v-model="fatThumb" :track-size="10" :thumb-size="28" />
</div>
</template>语义色
六种语义色对应当前值的填充色,与全局 --m-* 令牌联动。
<script setup lang="ts">
import { ref } from 'vue'
const colors = ['primary', 'secondary', 'success', 'warning', 'error', 'info'] as const
const values = ref([20, 35, 50, 65, 80, 95])
</script>
<template>
<div class="m-row-demo--stretch">
<MSlider v-for="(color, index) in colors" :key="color" v-model="values[index]" :color="color" />
</div>
</template>禁用、气泡与步进
disabled 时不可交互;showLabel="false" 关闭拖动时跟随拇指的数值气泡;step 决定取值的量化粒度。
<script setup lang="ts">
import { ref } from 'vue'
const locked = ref(60)
const quiet = ref(50)
const stepped = ref(20)
</script>
<template>
<div class="m-row-demo--stretch">
<MSlider v-model="locked" disabled />
<MSlider v-model="quiet" :show-label="false" />
<MSlider v-model="stepped" :min="0" :max="100" :step="10" />
<span>步进值(step = 10):{{ stepped }}</span>
</div>
</template>API
Props
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
modelValue | number | undefined(内部按 min 处理) | 当前值(v-model) |
min | number | 0 | 最小值 |
max | number | 100 | 最大值 |
step | number | 1 | 步进 |
disabled | boolean | false | 是否禁用 |
showLabel | boolean | true | 拖动 / 键盘调节时显示数值气泡 |
vertical | boolean | false | 纵向布局:轨道自上而下,最小值在底部,需由父容器提供高度 |
color | 'primary' | 'secondary' | 'success' | 'warning' | 'error' | 'info' | 'primary' | 语义色变体 |
size | 'small' | 'default' | 'large' | 'default' | 尺寸预设:同时缩放轨道粗细、拇指直径、描边与光圈 |
trackSize | number | undefined | 轨道粗细 px:覆盖 size 预设的轨道值,优先级最高 |
thumbSize | number | undefined | 拇指直径 px:覆盖 size 预设的拇指值,优先级最高 |
Events
| 事件 | 参数 | 说明 |
|---|---|---|
update:modelValue | value: number | 值变化(拖动中每帧最多一次) |
change | value: number | 拖动结束 / 键盘调节时触发 |
Slots
无。
尺寸预设
size 以 default(拇指 16px / 轨道 4px)为基准等比缩放,trackSize / thumbSize 会覆盖对应部分。
| 取值 | 缩放 | 拇指直径 | 轨道粗细 |
|---|---|---|---|
small | 0.75× | 12px | 3px |
default | 1× | 16px | 4px |
large | 1.5× | 24px | 6px |
使用建议
纵向滑块要给容器高度
vertical 时滑块根元素高度是 100%,尺寸完全来自父容器。用一层定高(或 flex: 1)的容器包住它是最省事的做法。
拖动中不要做重活
update:modelValue 已经按帧合帧,但每一帧仍会触发一次响应式更新。若下游依赖很重,建议只在 change 里做真正的业务处理。
trackSize / thumbSize 只接受有限正数
传入 0、负数或 NaN 会被忽略并回退到 size 预设值,不会把轨道或拇指变成不可见的尺寸。
点击轨道是跳转而非拖拽
点轨道会立即把值跳到该位置(带过渡),首次移动才进入拖拽态。需要「点击不改变值」的交互时要自行拦截。
相关组件
- InputNumber 数字输入框:需要精确输入或键盘长按步进时使用。
- Progress 进度条:只读展示进度、不接受输入时使用。