[breaking change] Stepper: rewrite

This commit is contained in:
陈嘉涵 2018-07-31 10:47:10 +08:00
parent 1ba7e7442d
commit 69e7e0c97b
8 changed files with 228 additions and 268 deletions

View File

@ -75,7 +75,7 @@ export default {
name: 'Select 选择',
path: '/pages/select/index'
}, {
name: 'Stepper 计数器',
name: 'Stepper 步进器',
path: '/pages/stepper/index'
}, {
name: 'Switch 开关',

View File

@ -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({});

View File

@ -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"
}

View File

@ -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>

View File

@ -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 | 减号按钮样式类 |

View File

@ -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);
}
}
});

View File

@ -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;
}
}
}

View File

@ -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>