mirror of
https://gitee.com/vant-contrib/vant-weapp.git
synced 2025-04-06 03:58:05 +08:00
[breaking change] Stepper: rewrite
This commit is contained in:
parent
1ba7e7442d
commit
69e7e0c97b
@ -75,7 +75,7 @@ export default {
|
||||
name: 'Select 选择',
|
||||
path: '/pages/select/index'
|
||||
}, {
|
||||
name: 'Stepper 计数器',
|
||||
name: 'Stepper 步进器',
|
||||
path: '/pages/stepper/index'
|
||||
}, {
|
||||
name: 'Switch 开关',
|
||||
|
@ -1,32 +1 @@
|
||||
Page(Object.assign({}, {
|
||||
data: {
|
||||
stepper1: {
|
||||
stepper: 10,
|
||||
min: 1
|
||||
},
|
||||
stepper2: {
|
||||
stepper: 10,
|
||||
min: 1,
|
||||
max: 20
|
||||
},
|
||||
stepper3: {
|
||||
stepper: 10,
|
||||
min: 1,
|
||||
max: 20,
|
||||
step: 2
|
||||
}
|
||||
},
|
||||
|
||||
handleZanStepperChange({
|
||||
detail: stepper,
|
||||
target: {
|
||||
dataset: {
|
||||
componentId
|
||||
}
|
||||
}
|
||||
}) {
|
||||
this.setData({
|
||||
[`${componentId}.stepper`]: stepper
|
||||
});
|
||||
}
|
||||
}));
|
||||
Page({});
|
||||
|
@ -1,6 +1,7 @@
|
||||
{
|
||||
"navigationBarTitleText": "Stepper 计数器",
|
||||
"navigationBarTitleText": "Stepper 步进器",
|
||||
"usingComponents": {
|
||||
"demo-block": "../../components/demo-block/index",
|
||||
"van-stepper": "../../dist/stepper/index",
|
||||
"van-panel": "../../dist/panel/index"
|
||||
}
|
||||
|
@ -1,60 +1,17 @@
|
||||
<van-panel title="基础用法">
|
||||
<view style="padding: 40px 15px">
|
||||
<van-stepper
|
||||
stepper="{{ stepper1.stepper }}"
|
||||
min="{{ stepper1.min }}"
|
||||
data-component-id="stepper1"
|
||||
bind:change="handleZanStepperChange"
|
||||
>
|
||||
</van-stepper>
|
||||
</view>
|
||||
</van-panel>
|
||||
<demo-block title="基础用法">
|
||||
<van-stepper value="{{ value1 }}" />
|
||||
</demo-block>
|
||||
|
||||
<!-- small size -->
|
||||
<van-panel title="不同尺寸-小尺寸类型">
|
||||
<view style="padding: 40px 15px">
|
||||
<view style="margin-bottom: 5px">small:</view>
|
||||
<van-stepper
|
||||
stepper="{{ stepper2.stepper }}"
|
||||
min="{{ stepper2.min }}"
|
||||
max="{{ stepper2.max }}"
|
||||
size="small"
|
||||
data-component-id="stepper2"
|
||||
bind:change="handleZanStepperChange"
|
||||
<demo-block title="禁用状态">
|
||||
<van-stepper value="{{ value1 }}" disabled />
|
||||
</demo-block>
|
||||
|
||||
></van-stepper>
|
||||
|
||||
<view style="margin: 10px 0 5px;">middle:</view>
|
||||
<van-stepper
|
||||
stepper="{{ stepper2.stepper }}"
|
||||
min="{{ stepper2.min }}"
|
||||
max="{{ stepper2.max }}"
|
||||
data-component-id="stepper2-1"
|
||||
bind:change="handleZanStepperChange"
|
||||
></van-stepper>
|
||||
|
||||
<view style="margin: 10px 0 5px;">large:</view>
|
||||
<van-stepper
|
||||
stepper="{{ stepper2.stepper }}"
|
||||
min="{{ stepper2.min }}"
|
||||
max="{{ stepper2.max }}"
|
||||
size="large"
|
||||
data-component-id="stepper2-2"
|
||||
bind:change="handleZanStepperChange"
|
||||
></van-stepper>
|
||||
</view>
|
||||
</van-panel>
|
||||
|
||||
<van-panel title="高级用法-每次变动数量自定义">
|
||||
<view style="padding: 40px 15px">
|
||||
<van-stepper
|
||||
stepper="{{ stepper3.stepper }}"
|
||||
min="{{ stepper3.min }}"
|
||||
max="{{ stepper3.max }}"
|
||||
step="{{ stepper3.step }}"
|
||||
data-component-id="stepper3"
|
||||
bind:change="handleZanStepperChange"
|
||||
>
|
||||
</van-stepper>
|
||||
</view>
|
||||
</van-panel>
|
||||
<demo-block title="高级用法">
|
||||
<van-stepper
|
||||
value="{{ value2 }}"
|
||||
integer
|
||||
min="5"
|
||||
max="40"
|
||||
step="2"
|
||||
/>
|
||||
</demo-block>
|
||||
|
@ -1,73 +1,72 @@
|
||||
## Stepper 计数器
|
||||
## Stepper 步进器
|
||||
|
||||
### 使用指南
|
||||
|
||||
在 index.json 中引入组件
|
||||
```json
|
||||
{
|
||||
"usingComponents": {
|
||||
"van-stepper": "path/to/vant-weapp/dist/stepper/index"
|
||||
}
|
||||
"usingComponents": {
|
||||
"van-stepper": "path/to/vant-weapp/dist/stepper/index"
|
||||
}
|
||||
```
|
||||
|
||||
### 代码演示
|
||||
|
||||
#### 基础用法
|
||||
`Stepper` 组件通过传入的 stepper 对象控制,内部数据格式如下:
|
||||
```js
|
||||
Page({
|
||||
data: {
|
||||
stepper: {
|
||||
// 当前 stepper 数字
|
||||
stepper: 1,
|
||||
// 最小可到的数字
|
||||
min: 1,
|
||||
// 最大可到的数字
|
||||
max: 1,
|
||||
// 尺寸
|
||||
size: 'small'
|
||||
}
|
||||
},
|
||||
|
||||
handleZanStepperChange({
|
||||
// stepper 代表操作后,应该要展示的数字,需要设置到数据对象里,才会更新页面展示
|
||||
detail: stepper
|
||||
}) {
|
||||
this.setData({
|
||||
'stepper.stepper': stepper
|
||||
});
|
||||
}
|
||||
});
|
||||
```html
|
||||
<van-stepper value="{{ 1 }}" bind:change="onChange" />
|
||||
```
|
||||
|
||||
当一个 `Stepper` 中,min 超过 max,就会导致组件被置灰。
|
||||
#### 禁用状态
|
||||
|
||||
当 stepper 被点击时,需要监听`change`事件,处理计数器值的改变。
|
||||
通过设置`disabled`属性来禁用 stepper
|
||||
|
||||
```js
|
||||
```html
|
||||
<van-stepper value="{{ 1 }}" disabled bind:change="onChange" />
|
||||
```
|
||||
|
||||
#### 高级用法
|
||||
|
||||
默认是每次加减为1,可以对组件设置`step`、`min`、`max`属性
|
||||
|
||||
```html
|
||||
<van-stepper
|
||||
stepper="{{ stepper.stepper }}"
|
||||
min="{{ stepper.min }}"
|
||||
max="{{ stepper.max }}"
|
||||
bind:change="handleZanStepperChange"
|
||||
>
|
||||
</van-stepper>
|
||||
value="{{ value }}"
|
||||
integer
|
||||
min="5"
|
||||
max="40"
|
||||
step="2"
|
||||
bind:change="onChange"
|
||||
/>
|
||||
```
|
||||
|
||||
### API
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 | 必须 |
|
||||
|-----------|-----------|-----------|-------------|-------------|
|
||||
| size | 计数器尺寸:small、middle、large | String | middle | |
|
||||
| stepper | 计数器的值 | Number | `1` | 必须 |
|
||||
| min | 计数器最小值 | Number | `1` | |
|
||||
| max | 计数器最大值 | Number | 无穷大 | |
|
||||
| step | 步数 | Number | `1` | |
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
|-----------|-----------|-----------|-------------|
|
||||
| value | 输入值 | `String | Number` | 最小值 |
|
||||
| min | 最小值 | `String | Number` | `1` |
|
||||
| max | 最大值 | `String | Number` | - |
|
||||
| step | 步数 | `String | Number` | `1` |
|
||||
| integer | 是否只允许输入整数 | `Boolean` | `false` |
|
||||
| disabled | 是否禁用 | `Boolean` | `false` |
|
||||
| disable-input | 是否禁用input框 | `Boolean` | `false` |
|
||||
|
||||
### Event
|
||||
|
||||
| 事件名称 | 说明 | 回调参数 |
|
||||
| 事件名称 | 说明 | 回调参数 |
|
||||
|-----------|-----------|-----------|
|
||||
| change | 当绑定值变化时触发的事件 | `{ index, stepper }` |
|
||||
| minus | 点击减少按钮时触发 | - |
|
||||
| change | 当绑定值变化时触发的事件 | event.detail: 当前输入的值 |
|
||||
| overlimit | 点击不可用的按钮时触发 | - |
|
||||
| plus | 点击增加按钮时触发 | - |
|
||||
| minus | 点击减少按钮时触发 | - |
|
||||
| blur | 输入框失焦时触发 | - |
|
||||
|
||||
### 外部样式类
|
||||
|
||||
| 类名 | 说明 |
|
||||
|-----------|-----------|
|
||||
| custom-class | 根节点样式类 |
|
||||
| input-class | 输入框样式类 |
|
||||
| plus-class | 加号按钮样式类 |
|
||||
| minus-class | 减号按钮样式类 |
|
||||
|
@ -1,79 +1,88 @@
|
||||
// Note that the bitwise operators and shift operators operate on 32-bit ints
|
||||
// so in that case, the max safe integer is 2^31-1, or 2147483647
|
||||
const VERY_LARGE_NUMBER = 2147483647;
|
||||
const MAX = 2147483647;
|
||||
|
||||
Component({
|
||||
externalClasses: [
|
||||
'custom-class',
|
||||
'input-class',
|
||||
'plus-class',
|
||||
'minus-class'
|
||||
],
|
||||
|
||||
properties: {
|
||||
size: {
|
||||
type: String,
|
||||
value: 'middle'
|
||||
},
|
||||
stepper: {
|
||||
type: Number,
|
||||
value: 1
|
||||
value: {
|
||||
type: null,
|
||||
observer(val) {
|
||||
if (val !== this.currentValue) {
|
||||
this.setData({ currentValue: this.range(val) });
|
||||
}
|
||||
}
|
||||
},
|
||||
integer: Boolean,
|
||||
disabled: Boolean,
|
||||
disableInput: Boolean,
|
||||
min: {
|
||||
type: Number,
|
||||
type: null,
|
||||
value: 1
|
||||
},
|
||||
max: {
|
||||
type: Number,
|
||||
value: VERY_LARGE_NUMBER
|
||||
type: null,
|
||||
value: MAX
|
||||
},
|
||||
step: {
|
||||
type: Number,
|
||||
type: null,
|
||||
value: 1
|
||||
}
|
||||
},
|
||||
|
||||
attached() {
|
||||
this.setData({
|
||||
currentValue: this.range(this.data.value)
|
||||
});
|
||||
},
|
||||
|
||||
methods: {
|
||||
handleZanStepperChange(e, type) {
|
||||
const { dataset = {} } = e.currentTarget;
|
||||
const { disabled } = dataset;
|
||||
const { step } = this.data;
|
||||
let { stepper } = this.data;
|
||||
|
||||
if (disabled) return null;
|
||||
|
||||
if (type === 'minus') {
|
||||
stepper -= step;
|
||||
} else if (type === 'plus') {
|
||||
stepper += step;
|
||||
}
|
||||
|
||||
if (stepper < this.data.min || stepper > this.data.max) return null;
|
||||
|
||||
this.triggerEvent('change', stepper);
|
||||
this.triggerEvent(type);
|
||||
// limit value range
|
||||
range(value) {
|
||||
return Math.max(Math.min(this.data.max, value), this.data.min);
|
||||
},
|
||||
|
||||
handleZanStepperMinus(e) {
|
||||
this.handleZanStepperChange(e, 'minus');
|
||||
onInput(event) {
|
||||
const { value = '' } = event.detail || {};
|
||||
this.triggerInput(value);
|
||||
},
|
||||
|
||||
handleZanStepperPlus(e) {
|
||||
this.handleZanStepperChange(e, 'plus');
|
||||
},
|
||||
|
||||
handleZanStepperBlur(e) {
|
||||
let { value } = e.detail;
|
||||
const { min, max } = this.data;
|
||||
|
||||
if (!value) {
|
||||
setTimeout(() => {
|
||||
this.triggerEvent('change', min);
|
||||
}, 16);
|
||||
onChange(type) {
|
||||
if (this[`${type}Disabled`]) {
|
||||
this.triggerEvent('overlimit', type);
|
||||
return;
|
||||
}
|
||||
|
||||
value = +value;
|
||||
if (value > max) {
|
||||
value = max;
|
||||
} else if (value < min) {
|
||||
value = min;
|
||||
}
|
||||
const diff = type === 'minus' ? -this.data.step : +this.data.step;
|
||||
const value = Math.round((this.data.currentValue + diff) * 100) / 100;
|
||||
this.triggerInput(this.range(value));
|
||||
this.triggerEvent(type);
|
||||
},
|
||||
|
||||
this.triggerEvent('change', value);
|
||||
onBlur(event) {
|
||||
const currentValue = this.range(this.data.currentValue);
|
||||
this.triggerInput(currentValue);
|
||||
this.triggerEvent('blur', event);
|
||||
},
|
||||
|
||||
onMinus() {
|
||||
this.onChange('minus');
|
||||
},
|
||||
|
||||
onPlus() {
|
||||
this.onChange('plus');
|
||||
},
|
||||
|
||||
triggerInput(currentValue) {
|
||||
this.setData({ currentValue });
|
||||
this.triggerEvent('input', currentValue);
|
||||
this.triggerEvent('change', currentValue);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -1,63 +1,93 @@
|
||||
@import '../helper/index.pcss';
|
||||
|
||||
.van-stepper {
|
||||
color: #666;
|
||||
}
|
||||
.van-stepper view {
|
||||
display: inline-block;
|
||||
padding: 5px 0;
|
||||
text-align: center;
|
||||
box-sizing: border-box;
|
||||
vertical-align: middle;
|
||||
font-size: 12px;
|
||||
border: 1rpx solid #999;
|
||||
}
|
||||
.van-stepper .van-stepper__minus {
|
||||
border-right: none;
|
||||
border-radius: 2px 0 0 2px;
|
||||
}
|
||||
.van-stepper .van-stepper__text {
|
||||
border: 1rpx solid #999;
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
/* 重置 input 默认样式 */
|
||||
min-height: auto;
|
||||
font-size: 12px;
|
||||
}
|
||||
.van-stepper .van-stepper__plus {
|
||||
border-left: none;
|
||||
border-radius: 0 2px 2px 0;
|
||||
}
|
||||
.van-stepper .van-stepper--disabled {
|
||||
background: #f8f8f8;
|
||||
color: #bbb;
|
||||
border-color: #e8e8e8;
|
||||
}
|
||||
.van-stepper--small view {
|
||||
min-width: 36px;
|
||||
line-height: 18px;
|
||||
}
|
||||
.van-stepper--small .van-stepper__text {
|
||||
width: 36px;
|
||||
line-height: 28px;
|
||||
height: 28px;
|
||||
}
|
||||
font-size: 0;
|
||||
|
||||
.van-stepper--middle view {
|
||||
min-width: 40px;
|
||||
line-height: 20px;
|
||||
}
|
||||
.van-stepper--middle .van-stepper__text {
|
||||
width: 40px;
|
||||
line-height: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
&__minus,
|
||||
&__plus,
|
||||
&__input {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
background-color: $white;
|
||||
}
|
||||
|
||||
.van-stepper--large view {
|
||||
min-width: 44px;
|
||||
line-height: 22px;
|
||||
}
|
||||
.van-stepper--large .van-stepper__text {
|
||||
width: 44px;
|
||||
line-height: 32px;
|
||||
height: 32px;
|
||||
&__minus,
|
||||
&__plus {
|
||||
width: 40px;
|
||||
height: 30px;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid $border-color;
|
||||
position: relative;
|
||||
padding: 5px;
|
||||
|
||||
&::before {
|
||||
width: 9px;
|
||||
height: 1px;
|
||||
}
|
||||
|
||||
&::after {
|
||||
width: 1px;
|
||||
height: 9px;
|
||||
}
|
||||
|
||||
&::before,
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
margin: auto;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: #6c6c6c;
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-color: $active-color;
|
||||
}
|
||||
|
||||
&--disabled {
|
||||
background-color: $background-color;
|
||||
|
||||
&::before,
|
||||
&::after {
|
||||
background-color: $gray;
|
||||
}
|
||||
}
|
||||
|
||||
&--disabled:active {
|
||||
background-color: $background-color;
|
||||
}
|
||||
}
|
||||
|
||||
&__minus {
|
||||
border-radius: 2px 0 0 2px;
|
||||
|
||||
&::after {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&__plus {
|
||||
border-radius: 0 2px 2px 0;
|
||||
}
|
||||
|
||||
&__input {
|
||||
width: 33px;
|
||||
height: 26px;
|
||||
padding: 1px;
|
||||
border: 1px solid $border-color;
|
||||
border-width: 1px 0;
|
||||
border-radius: 0;
|
||||
box-sizing: content-box;
|
||||
color: $gray-darker;
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
-webkit-appearance: none;
|
||||
|
||||
&--disabled {
|
||||
color: $gray;
|
||||
background-color: $background-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,23 +1,18 @@
|
||||
<view class="van-stepper van-stepper--{{ size }}">
|
||||
<view class="van-stepper custom-class">
|
||||
<view
|
||||
class="van-stepper__minus {{ stepper <= min ? 'van-stepper--disabled' : '' }}"
|
||||
data-disabled="{{ stepper <= min }}"
|
||||
bindtap="handleZanStepperMinus"
|
||||
>
|
||||
-
|
||||
</view>
|
||||
class="minus-class van-stepper__minus {{ disabled || currentValue <= min ? 'van-stepper__minus--disabled' : '' }}"
|
||||
bind:tap="onMinus"
|
||||
/>
|
||||
<input
|
||||
class="van-stepper__text {{ min >= max ? 'van-stepper--disabled' : '' }}"
|
||||
type="number"
|
||||
value="{{ stepper }}"
|
||||
disabled="{{ min >= max }}"
|
||||
bindblur="handleZanStepperBlur"
|
||||
type="{{ integer ? 'number' : 'digit' }}"
|
||||
class="input-class van-stepper__input {{ disabled || disableInput ? 'van-stepper__input--disabled' : '' }}"
|
||||
value="{{ currentValue }}"
|
||||
disabled="{{ disabled || disableInput }}"
|
||||
bindinput="onInput"
|
||||
bind:blur="onBlur"
|
||||
/>
|
||||
<view
|
||||
class="van-stepper__plus {{ stepper >= max ? 'van-stepper--disabled' : '' }}"
|
||||
data-disabled="{{ stepper >= max }}"
|
||||
bindtap="handleZanStepperPlus"
|
||||
>
|
||||
+
|
||||
</view>
|
||||
class="plus-class van-stepper__plus {{ disabled || currentValue >= max ? 'van-stepper__plus--disabled' : '' }}"
|
||||
bind:tap="onPlus"
|
||||
/>
|
||||
</view>
|
||||
|
Loading…
x
Reference in New Issue
Block a user