mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-24 10:20:19 +08:00
feat: migrate Slider component
This commit is contained in:
parent
e111fd4208
commit
75d76d2cec
123
src-next/slider/README.md
Normal file
123
src-next/slider/README.md
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
# Slider
|
||||||
|
|
||||||
|
### Install
|
||||||
|
|
||||||
|
```js
|
||||||
|
import Vue from 'vue';
|
||||||
|
import { Slider } from 'vant';
|
||||||
|
|
||||||
|
Vue.use(Slider);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Basic Usage
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-slider v-model="value" @change="onChange" />
|
||||||
|
```
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { Toast } from 'vant';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
value: 50,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onChange(value) {
|
||||||
|
Toast('Current value:' + value);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### Range
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-slider v-model="value" :min="-50" :max="50" />
|
||||||
|
```
|
||||||
|
|
||||||
|
### Disabled
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-slider v-model="value" disabled />
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step size
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-slider v-model="value" :step="10" />
|
||||||
|
```
|
||||||
|
|
||||||
|
### Custom style
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-slider v-model="value" bar-height="4px" active-color="#ee0a24" />
|
||||||
|
```
|
||||||
|
|
||||||
|
### Custom button
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-slider v-model="value" active-color="#ee0a24">
|
||||||
|
<template #button>
|
||||||
|
<div class="custom-button">
|
||||||
|
{{ value }}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</van-slider>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.custom-button {
|
||||||
|
width: 26px;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 10px;
|
||||||
|
line-height: 18px;
|
||||||
|
text-align: center;
|
||||||
|
background-color: #ee0a24;
|
||||||
|
border-radius: 100px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Vertical
|
||||||
|
|
||||||
|
```html
|
||||||
|
<div :style="{ height: '100px' }">
|
||||||
|
<van-slider v-model="value" vertical />
|
||||||
|
</div>
|
||||||
|
```
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
### Props
|
||||||
|
|
||||||
|
| Attribute | Description | Type | Default |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| value | Current value | _number_ | `0` |
|
||||||
|
| max | Max value | _number \| string_ | `100` |
|
||||||
|
| min | Min value | _number \| string_ | `0` |
|
||||||
|
| step | Step size | _number \| string_ | `1` |
|
||||||
|
| bar-height | Height of bar | _number \| string_ | `2px` |
|
||||||
|
| button-size `v2.4.5` | Button size | _number \| string_ | `24px` |
|
||||||
|
| active-color | Active color of bar | _string_ | `#1989fa` |
|
||||||
|
| inactive-color | Inactive color of bar | _string_ | `#e5e5e5` |
|
||||||
|
| disabled | Whether to disable slider | _boolean_ | `false` |
|
||||||
|
| vertical | Whether to display slider vertically | _boolean_ | `false` |
|
||||||
|
|
||||||
|
### Events
|
||||||
|
|
||||||
|
| Event | Description | Arguments |
|
||||||
|
| ---------- | ------------------------------------ | ------------------- |
|
||||||
|
| input | Instant triggered when value changed | value: current rate |
|
||||||
|
| change | Triggered after value changed | value: current rate |
|
||||||
|
| drag-start | Triggered when start drag | - |
|
||||||
|
| drag-end | Triggered when end drag | - |
|
||||||
|
|
||||||
|
### Slots
|
||||||
|
|
||||||
|
| Name | Description |
|
||||||
|
| ------ | ------------- |
|
||||||
|
| button | Custom button |
|
125
src-next/slider/README.zh-CN.md
Normal file
125
src-next/slider/README.zh-CN.md
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
# Slider 滑块
|
||||||
|
|
||||||
|
### 引入
|
||||||
|
|
||||||
|
```js
|
||||||
|
import Vue from 'vue';
|
||||||
|
import { Slider } from 'vant';
|
||||||
|
|
||||||
|
Vue.use(Slider);
|
||||||
|
```
|
||||||
|
|
||||||
|
## 代码演示
|
||||||
|
|
||||||
|
### 基础用法
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-slider v-model="value" @change="onChange" />
|
||||||
|
```
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { Toast } from 'vant';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
value: 50,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onChange(value) {
|
||||||
|
Toast('当前值:' + value);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### 指定选择范围
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-slider v-model="value" :min="-50" :max="50" />
|
||||||
|
```
|
||||||
|
|
||||||
|
### 禁用
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-slider v-model="value" disabled />
|
||||||
|
```
|
||||||
|
|
||||||
|
### 指定步长
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-slider v-model="value" :step="10" />
|
||||||
|
```
|
||||||
|
|
||||||
|
### 自定义样式
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-slider v-model="value" bar-height="4px" active-color="#ee0a24" />
|
||||||
|
```
|
||||||
|
|
||||||
|
### 自定义按钮
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-slider v-model="value" active-color="#ee0a24">
|
||||||
|
<template #button>
|
||||||
|
<div class="custom-button">
|
||||||
|
{{ value }}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</van-slider>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.custom-button {
|
||||||
|
width: 26px;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 10px;
|
||||||
|
line-height: 18px;
|
||||||
|
text-align: center;
|
||||||
|
background-color: #ee0a24;
|
||||||
|
border-radius: 100px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 垂直方向
|
||||||
|
|
||||||
|
Slider 垂直展示时,高度为 100% 父元素高度
|
||||||
|
|
||||||
|
```html
|
||||||
|
<div :style="{ height: '100px' }">
|
||||||
|
<van-slider v-model="value" vertical />
|
||||||
|
</div>
|
||||||
|
```
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
### Props
|
||||||
|
|
||||||
|
| 参数 | 说明 | 类型 | 默认值 |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| value | 当前进度百分比 | _number_ | `0` |
|
||||||
|
| max | 最大值 | _number \| string_ | `100` |
|
||||||
|
| min | 最小值 | _number \| string_ | `0` |
|
||||||
|
| step | 步长 | _number \| string_ | `1` |
|
||||||
|
| bar-height | 进度条高度,默认单位为`px` | _number \| string_ | `2px` |
|
||||||
|
| button-size `v2.4.5` | 滑块按钮大小,默认单位为`px` | _number \| string_ | `24px` |
|
||||||
|
| active-color | 进度条激活态颜色 | _string_ | `#1989fa` |
|
||||||
|
| inactive-color | 进度条非激活态颜色 | _string_ | `#e5e5e5` |
|
||||||
|
| disabled | 是否禁用滑块 | _boolean_ | `false` |
|
||||||
|
| vertical | 是否垂直展示 | _boolean_ | `false` |
|
||||||
|
|
||||||
|
### Events
|
||||||
|
|
||||||
|
| 事件名 | 说明 | 回调参数 |
|
||||||
|
| ---------- | ------------------------ | --------------- |
|
||||||
|
| input | 进度变化时实时触发 | value: 当前进度 |
|
||||||
|
| change | 进度变化且结束拖动后触发 | value: 当前进度 |
|
||||||
|
| drag-start | 开始拖动时触发 | - |
|
||||||
|
| drag-end | 结束拖动时触发 | - |
|
||||||
|
|
||||||
|
### Slots
|
||||||
|
|
||||||
|
| 名称 | 说明 |
|
||||||
|
| ------ | -------------- |
|
||||||
|
| button | 自定义滑动按钮 |
|
114
src-next/slider/demo/index.vue
Normal file
114
src-next/slider/demo/index.vue
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
<template>
|
||||||
|
<demo-section>
|
||||||
|
<demo-block :title="t('title1')">
|
||||||
|
<van-slider v-model="value1" @change="onChange" />
|
||||||
|
</demo-block>
|
||||||
|
|
||||||
|
<demo-block :title="t('title2')">
|
||||||
|
<van-slider v-model="value2" :min="-50" :max="50" @change="onChange" />
|
||||||
|
</demo-block>
|
||||||
|
|
||||||
|
<demo-block :title="t('title3')">
|
||||||
|
<van-slider v-model="value3" disabled />
|
||||||
|
</demo-block>
|
||||||
|
|
||||||
|
<demo-block :title="t('title4')">
|
||||||
|
<van-slider v-model="value4" :step="10" @change="onChange" />
|
||||||
|
</demo-block>
|
||||||
|
|
||||||
|
<demo-block :title="t('customStyle')">
|
||||||
|
<van-slider
|
||||||
|
v-model="value5"
|
||||||
|
bar-height="4px"
|
||||||
|
active-color="#ee0a24"
|
||||||
|
@change="onChange"
|
||||||
|
/>
|
||||||
|
</demo-block>
|
||||||
|
|
||||||
|
<demo-block :title="t('customButton')">
|
||||||
|
<van-slider v-model="value6" active-color="#ee0a24">
|
||||||
|
<template #button>
|
||||||
|
<div class="custom-button">{{ value6 }}</div>
|
||||||
|
</template>
|
||||||
|
</van-slider>
|
||||||
|
</demo-block>
|
||||||
|
|
||||||
|
<demo-block v-if="!isWeapp" :title="t('vertical')">
|
||||||
|
<div :style="{ height: '120px', paddingLeft: '30px' }">
|
||||||
|
<van-slider v-model="value7" vertical @change="onChange" />
|
||||||
|
</div>
|
||||||
|
</demo-block>
|
||||||
|
</demo-section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
i18n: {
|
||||||
|
'zh-CN': {
|
||||||
|
title1: '基础用法',
|
||||||
|
title2: '指定选择范围',
|
||||||
|
title3: '禁用',
|
||||||
|
title4: '指定步长',
|
||||||
|
customStyle: '自定义样式',
|
||||||
|
customButton: '自定义按钮',
|
||||||
|
text: '当前值:',
|
||||||
|
vertical: '垂直方向',
|
||||||
|
},
|
||||||
|
'en-US': {
|
||||||
|
title1: 'Basic Usage',
|
||||||
|
title2: 'Range',
|
||||||
|
title3: 'Disabled',
|
||||||
|
title4: 'Step size',
|
||||||
|
customStyle: 'Custom Style',
|
||||||
|
customButton: 'Custom Button',
|
||||||
|
text: 'Current value: ',
|
||||||
|
vertical: 'Vertical',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
value1: 50,
|
||||||
|
value2: 0,
|
||||||
|
value3: 50,
|
||||||
|
value4: 50,
|
||||||
|
value5: 50,
|
||||||
|
value6: 50,
|
||||||
|
value7: 50,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
onChange(value) {
|
||||||
|
this.$toast(this.t('text') + value);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less">
|
||||||
|
@import '../../style/var';
|
||||||
|
|
||||||
|
.demo-slider {
|
||||||
|
background: @white;
|
||||||
|
user-select: none;
|
||||||
|
|
||||||
|
.van-doc-demo-block {
|
||||||
|
padding: 0 @padding-md 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.van-doc-demo-block__title {
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-button {
|
||||||
|
width: 26px;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 10px;
|
||||||
|
line-height: 18px;
|
||||||
|
text-align: center;
|
||||||
|
background-color: @red;
|
||||||
|
border-radius: 100px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
195
src-next/slider/index.js
Normal file
195
src-next/slider/index.js
Normal file
@ -0,0 +1,195 @@
|
|||||||
|
import { createNamespace, addUnit } from '../utils';
|
||||||
|
import { preventDefault } from '../utils/dom/event';
|
||||||
|
import { TouchMixin } from '../mixins/touch';
|
||||||
|
import { FieldMixin } from '../mixins/field';
|
||||||
|
|
||||||
|
const [createComponent, bem] = createNamespace('slider');
|
||||||
|
|
||||||
|
export default createComponent({
|
||||||
|
mixins: [TouchMixin, FieldMixin],
|
||||||
|
|
||||||
|
props: {
|
||||||
|
disabled: Boolean,
|
||||||
|
vertical: Boolean,
|
||||||
|
barHeight: [Number, String],
|
||||||
|
buttonSize: [Number, String],
|
||||||
|
activeColor: String,
|
||||||
|
inactiveColor: String,
|
||||||
|
min: {
|
||||||
|
type: [Number, String],
|
||||||
|
default: 0,
|
||||||
|
},
|
||||||
|
max: {
|
||||||
|
type: [Number, String],
|
||||||
|
default: 100,
|
||||||
|
},
|
||||||
|
step: {
|
||||||
|
type: [Number, String],
|
||||||
|
default: 1,
|
||||||
|
},
|
||||||
|
modelValue: {
|
||||||
|
type: Number,
|
||||||
|
default: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
dragStatus: '',
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
range() {
|
||||||
|
return this.max - this.min;
|
||||||
|
},
|
||||||
|
|
||||||
|
buttonStyle() {
|
||||||
|
if (this.buttonSize) {
|
||||||
|
const size = addUnit(this.buttonSize);
|
||||||
|
return {
|
||||||
|
width: size,
|
||||||
|
height: size,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
created() {
|
||||||
|
// format initial value
|
||||||
|
this.updateValue(this.modelValue);
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
this.bindTouchEvent(this.$refs.wrapper);
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
onTouchStart(event) {
|
||||||
|
if (this.disabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.touchStart(event);
|
||||||
|
this.startValue = this.format(this.modelValue);
|
||||||
|
this.dragStatus = 'start';
|
||||||
|
},
|
||||||
|
|
||||||
|
onTouchMove(event) {
|
||||||
|
if (this.disabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.dragStatus === 'start') {
|
||||||
|
this.$emit('drag-start');
|
||||||
|
}
|
||||||
|
|
||||||
|
preventDefault(event, true);
|
||||||
|
this.touchMove(event);
|
||||||
|
this.dragStatus = 'draging';
|
||||||
|
|
||||||
|
const rect = this.$el.getBoundingClientRect();
|
||||||
|
const delta = this.vertical ? this.deltaY : this.deltaX;
|
||||||
|
const total = this.vertical ? rect.height : rect.width;
|
||||||
|
const diff = (delta / total) * this.range;
|
||||||
|
|
||||||
|
this.newValue = this.startValue + diff;
|
||||||
|
this.updateValue(this.newValue);
|
||||||
|
},
|
||||||
|
|
||||||
|
onTouchEnd() {
|
||||||
|
if (this.disabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.dragStatus === 'draging') {
|
||||||
|
this.updateValue(this.newValue, true);
|
||||||
|
this.$emit('drag-end');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.dragStatus = '';
|
||||||
|
},
|
||||||
|
|
||||||
|
onClick(event) {
|
||||||
|
event.stopPropagation();
|
||||||
|
|
||||||
|
if (this.disabled) return;
|
||||||
|
|
||||||
|
const rect = this.$el.getBoundingClientRect();
|
||||||
|
const delta = this.vertical
|
||||||
|
? event.clientY - rect.top
|
||||||
|
: event.clientX - rect.left;
|
||||||
|
const total = this.vertical ? rect.height : rect.width;
|
||||||
|
const value = +this.min + (delta / total) * this.range;
|
||||||
|
|
||||||
|
this.startValue = this.modelValue;
|
||||||
|
this.updateValue(value, true);
|
||||||
|
},
|
||||||
|
|
||||||
|
updateValue(value, end) {
|
||||||
|
value = this.format(value);
|
||||||
|
|
||||||
|
if (value !== this.modelValue) {
|
||||||
|
this.$emit('update:modelValue', value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (end && value !== this.startValue) {
|
||||||
|
this.$emit('change', value);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
format(value) {
|
||||||
|
return (
|
||||||
|
Math.round(Math.max(this.min, Math.min(value, this.max)) / this.step) *
|
||||||
|
this.step
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { vertical } = this;
|
||||||
|
const mainAxis = vertical ? 'height' : 'width';
|
||||||
|
const crossAxis = vertical ? 'width' : 'height';
|
||||||
|
|
||||||
|
const wrapperStyle = {
|
||||||
|
background: this.inactiveColor,
|
||||||
|
[crossAxis]: addUnit(this.barHeight),
|
||||||
|
};
|
||||||
|
|
||||||
|
const barStyle = {
|
||||||
|
[mainAxis]: `${((this.modelValue - this.min) * 100) / this.range}%`,
|
||||||
|
background: this.activeColor,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (this.dragStatus) {
|
||||||
|
barStyle.transition = 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
style={wrapperStyle}
|
||||||
|
class={bem({ disabled: this.disabled, vertical })}
|
||||||
|
onClick={this.onClick}
|
||||||
|
>
|
||||||
|
<div class={bem('bar')} style={barStyle}>
|
||||||
|
<div
|
||||||
|
ref="wrapper"
|
||||||
|
role="slider"
|
||||||
|
tabindex={this.disabled ? -1 : 0}
|
||||||
|
aria-valuemin={this.min}
|
||||||
|
aria-valuenow={this.modelValue}
|
||||||
|
aria-valuemax={this.max}
|
||||||
|
aria-orientation={this.vertical ? 'vertical' : 'horizontal'}
|
||||||
|
class={bem('button-wrapper')}
|
||||||
|
>
|
||||||
|
{this.$slots.button ? (
|
||||||
|
this.$slots.button()
|
||||||
|
) : (
|
||||||
|
<div class={bem('button')} style={this.buttonStyle} />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
75
src-next/slider/index.less
Normal file
75
src-next/slider/index.less
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
@import '../style/var';
|
||||||
|
|
||||||
|
.van-slider {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: @slider-bar-height;
|
||||||
|
background-color: @slider-inactive-background-color;
|
||||||
|
border-radius: @border-radius-max;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
// use pseudo element to expand click area
|
||||||
|
&::before {
|
||||||
|
position: absolute;
|
||||||
|
top: -@padding-xs;
|
||||||
|
right: 0;
|
||||||
|
bottom: -@padding-xs;
|
||||||
|
left: 0;
|
||||||
|
content: '';
|
||||||
|
}
|
||||||
|
|
||||||
|
&__bar {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: @slider-active-background-color;
|
||||||
|
border-radius: inherit;
|
||||||
|
transition: width @animation-duration-fast;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__button {
|
||||||
|
width: @slider-button-width;
|
||||||
|
height: @slider-button-height;
|
||||||
|
background-color: @slider-button-background-color;
|
||||||
|
border-radius: @slider-button-border-radius;
|
||||||
|
box-shadow: @slider-button-box-shadow;
|
||||||
|
|
||||||
|
&-wrapper {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
right: 0;
|
||||||
|
transform: translate3d(50%, -50%, 0);
|
||||||
|
cursor: grab;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--disabled {
|
||||||
|
cursor: not-allowed;
|
||||||
|
opacity: @slider-disabled-opacity;
|
||||||
|
|
||||||
|
.van-slider__button-wrapper {
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--vertical {
|
||||||
|
display: inline-block;
|
||||||
|
width: @slider-bar-height;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
.van-slider__button-wrapper {
|
||||||
|
top: auto;
|
||||||
|
right: 50%;
|
||||||
|
bottom: 0;
|
||||||
|
transform: translate3d(50%, 50%, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// use pseudo element to expand click area
|
||||||
|
&::before {
|
||||||
|
top: 0;
|
||||||
|
right: -@padding-xs;
|
||||||
|
bottom: 0;
|
||||||
|
left: -@padding-xs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
71
src-next/slider/test/__snapshots__/demo.spec.js.snap
Normal file
71
src-next/slider/test/__snapshots__/demo.spec.js.snap
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`renders demo correctly 1`] = `
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<div class="van-slider">
|
||||||
|
<div class="van-slider__bar" style="width: 50%;">
|
||||||
|
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuenow="50" aria-valuemax="100" aria-orientation="horizontal" class="van-slider__button-wrapper">
|
||||||
|
<div class="van-slider__button"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="van-slider">
|
||||||
|
<div class="van-slider__bar" style="width: 50%;">
|
||||||
|
<div role="slider" tabindex="0" aria-valuemin="-50" aria-valuenow="0" aria-valuemax="50" aria-orientation="horizontal" class="van-slider__button-wrapper">
|
||||||
|
<div class="van-slider__button"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="van-slider van-slider--disabled">
|
||||||
|
<div class="van-slider__bar" style="width: 50%;">
|
||||||
|
<div role="slider" tabindex="-1" aria-valuemin="0" aria-valuenow="50" aria-valuemax="100" aria-orientation="horizontal" class="van-slider__button-wrapper">
|
||||||
|
<div class="van-slider__button"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="van-slider">
|
||||||
|
<div class="van-slider__bar" style="width: 50%;">
|
||||||
|
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuenow="50" aria-valuemax="100" aria-orientation="horizontal" class="van-slider__button-wrapper">
|
||||||
|
<div class="van-slider__button"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="van-slider" style="height: 4px;">
|
||||||
|
<div class="van-slider__bar" style="width: 50%; background: rgb(238, 10, 36);">
|
||||||
|
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuenow="50" aria-valuemax="100" aria-orientation="horizontal" class="van-slider__button-wrapper">
|
||||||
|
<div class="van-slider__button"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="van-slider">
|
||||||
|
<div class="van-slider__bar" style="width: 50%; background: rgb(238, 10, 36);">
|
||||||
|
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuenow="50" aria-valuemax="100" aria-orientation="horizontal" class="van-slider__button-wrapper">
|
||||||
|
<div class="custom-button">50</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div style="height: 120px; padding-left: 30px;">
|
||||||
|
<div class="van-slider van-slider--vertical">
|
||||||
|
<div class="van-slider__bar" style="height: 50%;">
|
||||||
|
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuenow="50" aria-valuemax="100" aria-orientation="vertical" class="van-slider__button-wrapper">
|
||||||
|
<div class="van-slider__button"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
81
src-next/slider/test/__snapshots__/index.spec.js.snap
Normal file
81
src-next/slider/test/__snapshots__/index.spec.js.snap
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`bar-height prop 1`] = `
|
||||||
|
<div class="van-slider" style="height: 10px;">
|
||||||
|
<div class="van-slider__bar" style="width: 50%;">
|
||||||
|
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuenow="50" aria-valuemax="100" aria-orientation="horizontal" class="van-slider__button-wrapper">
|
||||||
|
<div class="van-slider__button"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`button-size prop 1`] = `
|
||||||
|
<div class="van-slider">
|
||||||
|
<div class="van-slider__bar" style="width: 50%;">
|
||||||
|
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuenow="50" aria-valuemax="100" aria-orientation="horizontal" class="van-slider__button-wrapper">
|
||||||
|
<div class="van-slider__button" style="width: 10px; height: 10px;"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`click bar 1`] = `
|
||||||
|
<div class="van-slider van-slider--disabled">
|
||||||
|
<div class="van-slider__bar" style="width: 50%;">
|
||||||
|
<div role="slider" tabindex="-1" aria-valuemin="0" aria-valuenow="50" aria-valuemax="100" aria-orientation="horizontal" class="van-slider__button-wrapper">
|
||||||
|
<div class="van-slider__button"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`click bar 2`] = `
|
||||||
|
<div class="van-slider">
|
||||||
|
<div class="van-slider__bar" style="width: 100%;">
|
||||||
|
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuenow="100" aria-valuemax="100" aria-orientation="horizontal" class="van-slider__button-wrapper">
|
||||||
|
<div class="van-slider__button"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`click vertical 1`] = `
|
||||||
|
<div class="van-slider van-slider--vertical">
|
||||||
|
<div class="van-slider__bar" style="height: 100%;">
|
||||||
|
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuenow="100" aria-valuemax="100" aria-orientation="vertical" class="van-slider__button-wrapper">
|
||||||
|
<div class="van-slider__button"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`drag button 1`] = `
|
||||||
|
<div class="van-slider van-slider--disabled">
|
||||||
|
<div class="van-slider__bar" style="width: 50%;">
|
||||||
|
<div role="slider" tabindex="-1" aria-valuemin="0" aria-valuenow="50" aria-valuemax="100" aria-orientation="horizontal" class="van-slider__button-wrapper">
|
||||||
|
<div class="van-slider__button"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`drag button 2`] = `
|
||||||
|
<div class="van-slider">
|
||||||
|
<div class="van-slider__bar" style="width: 100%;">
|
||||||
|
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuenow="100" aria-valuemax="100" aria-orientation="horizontal" class="van-slider__button-wrapper">
|
||||||
|
<div class="van-slider__button"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`drag button vertical 1`] = `
|
||||||
|
<div class="van-slider van-slider--vertical">
|
||||||
|
<div class="van-slider__bar" style="height: 100%;">
|
||||||
|
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuenow="100" aria-valuemax="100" aria-orientation="vertical" class="van-slider__button-wrapper">
|
||||||
|
<div class="van-slider__button"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
4
src-next/slider/test/demo.spec.js
Normal file
4
src-next/slider/test/demo.spec.js
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
import Demo from '../demo';
|
||||||
|
import { snapshotDemo } from '../../../test/demo';
|
||||||
|
|
||||||
|
snapshotDemo(Demo);
|
166
src-next/slider/test/index.spec.js
Normal file
166
src-next/slider/test/index.spec.js
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
import Slider from '..';
|
||||||
|
import {
|
||||||
|
mount,
|
||||||
|
trigger,
|
||||||
|
triggerDrag,
|
||||||
|
mockGetBoundingClientRect,
|
||||||
|
} from '../../../test';
|
||||||
|
|
||||||
|
function mockRect(vertical) {
|
||||||
|
return mockGetBoundingClientRect({
|
||||||
|
width: vertical ? 0 : 100,
|
||||||
|
height: vertical ? 100 : 0,
|
||||||
|
top: vertical ? 0 : 100,
|
||||||
|
left: vertical ? 100 : 0,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
test('drag button', () => {
|
||||||
|
const restoreMock = mockRect();
|
||||||
|
|
||||||
|
const wrapper = mount(Slider, {
|
||||||
|
propsData: {
|
||||||
|
value: 50,
|
||||||
|
disabled: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
wrapper.vm.$on('input', (value) => {
|
||||||
|
wrapper.setProps({ value });
|
||||||
|
});
|
||||||
|
|
||||||
|
const button = wrapper.find('.van-slider__button');
|
||||||
|
triggerDrag(button, 50, 0);
|
||||||
|
expect(wrapper).toMatchSnapshot();
|
||||||
|
expect(wrapper.emitted('drag-start')).toBeFalsy();
|
||||||
|
expect(wrapper.emitted('drag-end')).toBeFalsy();
|
||||||
|
|
||||||
|
wrapper.setData({ disabled: false });
|
||||||
|
trigger(button, 'touchstart', 0, 0);
|
||||||
|
trigger(button, 'touchend', 0, 0);
|
||||||
|
triggerDrag(button, 50, 0);
|
||||||
|
expect(wrapper).toMatchSnapshot();
|
||||||
|
expect(wrapper.emitted('drag-start')).toBeTruthy();
|
||||||
|
expect(wrapper.emitted('drag-end')).toBeTruthy();
|
||||||
|
|
||||||
|
restoreMock();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('click bar', () => {
|
||||||
|
const restoreMock = mockRect();
|
||||||
|
|
||||||
|
const wrapper = mount(Slider, {
|
||||||
|
propsData: {
|
||||||
|
value: 50,
|
||||||
|
disabled: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
wrapper.vm.$on('input', (value) => {
|
||||||
|
wrapper.setProps({ value });
|
||||||
|
});
|
||||||
|
|
||||||
|
trigger(wrapper, 'click', 100, 0);
|
||||||
|
expect(wrapper).toMatchSnapshot();
|
||||||
|
|
||||||
|
wrapper.setData({ disabled: false });
|
||||||
|
trigger(wrapper, 'click', 100, 0);
|
||||||
|
expect(wrapper).toMatchSnapshot();
|
||||||
|
|
||||||
|
restoreMock();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('drag button vertical', () => {
|
||||||
|
const restoreMock = mockRect(true);
|
||||||
|
|
||||||
|
const wrapper = mount(Slider, {
|
||||||
|
propsData: {
|
||||||
|
value: 50,
|
||||||
|
vertical: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
wrapper.vm.$on('input', (value) => {
|
||||||
|
wrapper.setProps({ value });
|
||||||
|
});
|
||||||
|
|
||||||
|
const button = wrapper.find('.van-slider__button');
|
||||||
|
triggerDrag(button, 0, 50);
|
||||||
|
expect(wrapper).toMatchSnapshot();
|
||||||
|
|
||||||
|
restoreMock();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('click vertical', () => {
|
||||||
|
const restoreMock = mockRect(true);
|
||||||
|
|
||||||
|
const wrapper = mount(Slider, {
|
||||||
|
propsData: {
|
||||||
|
value: 50,
|
||||||
|
vertical: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
wrapper.vm.$on('input', (value) => {
|
||||||
|
wrapper.setProps({ value });
|
||||||
|
});
|
||||||
|
|
||||||
|
trigger(wrapper, 'click', 0, 100);
|
||||||
|
expect(wrapper).toMatchSnapshot();
|
||||||
|
|
||||||
|
restoreMock();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('bar-height prop', () => {
|
||||||
|
const wrapper = mount(Slider, {
|
||||||
|
propsData: {
|
||||||
|
value: 50,
|
||||||
|
barHeight: 10,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(wrapper).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('button-size prop', () => {
|
||||||
|
const wrapper = mount(Slider, {
|
||||||
|
propsData: {
|
||||||
|
value: 50,
|
||||||
|
buttonSize: 10,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(wrapper).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should not emit change event when value not changed', () => {
|
||||||
|
const wrapper = mount(Slider, {
|
||||||
|
propsData: {
|
||||||
|
value: 50,
|
||||||
|
},
|
||||||
|
listeners: {
|
||||||
|
input(value) {
|
||||||
|
wrapper.setProps({ value });
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
trigger(wrapper, 'click', 100, 0);
|
||||||
|
trigger(wrapper, 'click', 100, 0);
|
||||||
|
|
||||||
|
expect(wrapper.emitted('change').length).toEqual(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should format initial value', (done) => {
|
||||||
|
mount(Slider, {
|
||||||
|
propsData: {
|
||||||
|
value: null,
|
||||||
|
},
|
||||||
|
listeners: {
|
||||||
|
input(value) {
|
||||||
|
expect(value).toEqual(0);
|
||||||
|
done();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
@ -159,10 +159,10 @@ module.exports = {
|
|||||||
// path: 'search',
|
// path: 'search',
|
||||||
// title: 'Search 搜索',
|
// title: 'Search 搜索',
|
||||||
// },
|
// },
|
||||||
// {
|
{
|
||||||
// path: 'slider',
|
path: 'slider',
|
||||||
// title: 'Slider 滑块',
|
title: 'Slider 滑块',
|
||||||
// },
|
},
|
||||||
// {
|
// {
|
||||||
// path: 'stepper',
|
// path: 'stepper',
|
||||||
// title: 'Stepper 步进器',
|
// title: 'Stepper 步进器',
|
||||||
@ -493,10 +493,10 @@ module.exports = {
|
|||||||
// path: 'search',
|
// path: 'search',
|
||||||
// title: 'Search',
|
// title: 'Search',
|
||||||
// },
|
// },
|
||||||
// {
|
{
|
||||||
// path: 'slider',
|
path: 'slider',
|
||||||
// title: 'Slider',
|
title: 'Slider',
|
||||||
// },
|
},
|
||||||
// {
|
// {
|
||||||
// path: 'stepper',
|
// path: 'stepper',
|
||||||
// title: 'Stepper',
|
// title: 'Stepper',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user