Quantity: rename to Stepper

This commit is contained in:
陈嘉涵 2017-09-08 11:36:03 +08:00
parent 378ef55a0a
commit 6ec9d9852a
13 changed files with 72 additions and 384 deletions

View File

@ -8,7 +8,7 @@ export default {
} }
</script> </script>
## Card 图文组件 ## Card 图文
### 使用指南 ### 使用指南
``` javascript ``` javascript

View File

@ -74,7 +74,7 @@ export default {
} }
</script> </script>
## DeepSelect 分类选择组件 ## DeepSelect 分类选择
### 使用指南 ### 使用指南
``` javascript ``` javascript

View File

@ -73,7 +73,7 @@ export default {
}; };
</script> </script>
## Popup 弹出菜单 ## Popup 弹出
### 使用指南 ### 使用指南
``` javascript ``` javascript
@ -107,11 +107,11 @@ export default {
``` ```
::: :::
#### 从不同位置弹出菜单 #### 从不同位置弹出
可以设置`position`属性,`popup`即能从不同位置弹出,`position`的可选值有`top``bottom``right``left` 可以设置`position`属性,`popup`即能从不同位置弹出,`position`的可选值有`top``bottom``right``left`
:::demo 从不同位置弹出菜单 :::demo 从不同位置弹出
```html ```html
<van-button @click="popupShow2 = true;">从下方弹出popup</van-button> <van-button @click="popupShow2 = true;">从下方弹出popup</van-button>
<van-popup v-model="popupShow2" position="bottom" class="van-popup-2"> <van-popup v-model="popupShow2" position="bottom" class="van-popup-2">
@ -166,7 +166,7 @@ export default {
| v-model | 当前组件是否显示 | `Boolean` | `false` | - | | v-model | 当前组件是否显示 | `Boolean` | `false` | - |
| overlay | 是否显示背景遮罩层 | `Boolean` | `true` | - | | overlay | 是否显示背景遮罩层 | `Boolean` | `true` | - |
| lockOnScroll | 背景是否跟随滚动 | `Boolean` | `false` | - | | lockOnScroll | 背景是否跟随滚动 | `Boolean` | `false` | - |
| position | 弹出菜单位置 | `String` | - | `top`, `bottom`, `right`, `left` | | position | 弹出位置 | `String` | - | `top`, `bottom`, `right`, `left` |
| closeOnClickOverlay | 点击遮罩层是否关闭弹出菜单 | `Boolean` | `true` | - | | closeOnClickOverlay | 点击遮罩层是否关闭弹出 | `Boolean` | `true` | - |
| transition | 弹出菜单`transition` | `String` | `popup-slide` | | | transition | 弹出`transition` | `String` | `popup-slide` | |
| preventScroll | 是否防止滚动穿透 | `Boolean` | `false` | - | | preventScroll | 是否防止滚动穿透 | `Boolean` | `false` | - |

View File

@ -1,10 +1,10 @@
<style> <style>
.demo-quantity { .demo-stepper {
.van-quantity { .van-stepper {
margin-left: 15px; margin-left: 15px;
} }
.curr-quantity { .curr-stepper {
margin: 15px; margin: 15px;
} }
} }
@ -14,20 +14,20 @@
export default { export default {
data() { data() {
return { return {
quantity1: 1, stepper1: 1,
quantity2: null, stepper2: null,
}; };
} }
}; };
</script> </script>
## Quantity 数量选择 ## Stepper 步进器
### 使用指南 ### 使用指南
``` javascript ``` javascript
import { Quantity } from 'vant'; import { Stepper } from 'vant';
Vue.component(Quantity.name, Quantity); Vue.component(Stepper.name, Stepper);
``` ```
### 代码演示 ### 代码演示
@ -36,29 +36,28 @@ Vue.component(Quantity.name, Quantity);
:::demo 基础用法 :::demo 基础用法
```html ```html
<van-quantity v-model="quantity1"></van-quantity> <van-stepper v-model="stepper1"></van-stepper>
<p class="curr-quantity">当前值:{{ quantity1 }}</p> <p class="curr-stepper">当前值:{{ stepper1 }}</p>
``` ```
::: :::
#### 禁用Quantity #### 禁用状态
通过设置`disabled`属性来禁用 stepper
设置`disabled`属性,此时`quantity`不可改变。 :::demo 禁用状态
:::demo 禁用Quantity
```html ```html
<van-quantity v-model="quantity1" disabled></van-quantity> <van-stepper v-model="stepper1" disabled></van-stepper>
``` ```
::: :::
#### 高级用法 #### 高级用法
默认是每次加减为1可以对组件设置`step``min``max``defaultValue`属性 默认是每次加减为1可以对组件设置`step``min``max``defaultValue`属性
:::demo 高级用法 :::demo 高级用法
```html ```html
<van-quantity v-model="quantity2" min="5" max="40" step="2" default-value="9"></van-quantity> <van-stepper v-model="stepper2" min="5" max="40" step="2" default-value="9"></van-stepper>
<p class="curr-quantity">当前值:{{ quantity2 || 9 }}</p> <p class="curr-stepper">当前值:{{ stepper2 || 9 }}</p>
``` ```
::: :::

View File

@ -60,16 +60,12 @@ module.exports = {
}, },
{ {
"path": "/card", "path": "/card",
"title": "Card 图文组件" "title": "Card 图文"
}, },
{ {
"path": "/cell", "path": "/cell",
"title": "Cell 单元格" "title": "Cell 单元格"
}, },
{
"path": "/cell-swipe",
"title": "CellSwipe 滑动单元格"
},
{ {
"path": "/icon", "path": "/icon",
"title": "Icon 图标" "title": "Icon 图标"
@ -96,15 +92,15 @@ module.exports = {
}, },
{ {
"path": "/popup", "path": "/popup",
"title": "Popup 弹出菜单" "title": "Popup 弹出"
}, },
{ {
"path": "/progress", "path": "/progress",
"title": "Progress 进度条" "title": "Progress 进度条"
}, },
{ {
"path": "/quantity", "path": "/stepper",
"title": "Quantity 数量选择" "title": "Stepper 步进器"
}, },
{ {
"path": "/steps", "path": "/steps",
@ -189,6 +185,10 @@ module.exports = {
{ {
"groupName": "高阶组件", "groupName": "高阶组件",
"list": [ "list": [
{
"path": "/cell-swipe",
"title": "CellSwipe 滑动单元格"
},
{ {
"path": "/switch-cell", "path": "/switch-cell",
"title": "SwitchCell 开关单元格" "title": "SwitchCell 开关单元格"
@ -204,7 +204,7 @@ module.exports = {
}, },
{ {
"path": "/deep-select", "path": "/deep-select",
"title": "DeepSelect 分类选择组件" "title": "DeepSelect 分类选择"
}, },
{ {
"path": "/goods-action", "path": "/goods-action",

View File

@ -30,7 +30,7 @@ import Picker from './picker';
import Popup from './popup'; import Popup from './popup';
import Progress from './progress'; import Progress from './progress';
import PullRefresh from './pull-refresh'; import PullRefresh from './pull-refresh';
import Quantity from './quantity'; import Stepper from './stepper';
import Radio from './radio'; import Radio from './radio';
import RadioGroup from './radio-group'; import RadioGroup from './radio-group';
import Row from './row'; import Row from './row';
@ -79,7 +79,7 @@ const components = [
Popup, Popup,
Progress, Progress,
PullRefresh, PullRefresh,
Quantity, Stepper,
Radio, Radio,
RadioGroup, RadioGroup,
Row, Row,
@ -144,7 +144,7 @@ export {
Popup, Popup,
Progress, Progress,
PullRefresh, PullRefresh,
Quantity, Stepper,
Radio, Radio,
RadioGroup, RadioGroup,
Row, Row,

View File

@ -1,23 +1,23 @@
<template> <template>
<div class="van-quantity" :class="{ 'van-quantity--disabled': disabled }"> <div class="van-stepper" :class="{ 'van-stepper--disabled': disabled }">
<button <button
@click="handleChange('minus')" @click="handleChange('minus')"
class="van-quantity__stepper van-quantity__minus" class="van-stepper__stepper van-stepper__minus"
:class="{ :class="{
'van-quantity__minus--disabled': isMinusDisabled 'van-stepper__minus--disabled': isMinusDisabled
}"> }">
</button> </button>
<input <input
type="text" type="text"
class="van-quantity__input" class="van-stepper__input"
:value="currentValue" :value="currentValue"
@input="handleInputChange" @input="handleInputChange"
:disabled="disabled"> :disabled="disabled">
<button <button
@click="handleChange('plus')" @click="handleChange('plus')"
class="van-quantity__stepper van-quantity__plus" class="van-stepper__stepper van-stepper__plus"
:class="{ :class="{
'van-quantity__plus--disabled': isPlusDisabled 'van-stepper__plus--disabled': isPlusDisabled
}"> }">
</button> </button>
</div> </div>
@ -25,7 +25,7 @@
<script> <script>
export default { export default {
name: 'van-quantity', name: 'van-stepper',
props: { props: {
min: { min: {

View File

@ -23,7 +23,7 @@
@import './tag.css'; @import './tag.css';
@import './tab.css'; @import './tab.css';
@import './image-preview.css'; @import './image-preview.css';
@import './quantity.css'; @import './stepper.css';
@import './progress.css'; @import './progress.css';
@import './swipe.css'; @import './swipe.css';

View File

@ -1,12 +1,12 @@
@import './common/var.css'; @import './common/var.css';
.van-quantity { .van-stepper {
font-size: 0; font-size: 0;
&--disabled { &--disabled {
.van-quantity__input, .van-stepper__input,
.van-quantity__minus, .van-stepper__minus,
.van-quantity__plus { .van-stepper__plus {
border-color: $active-color; border-color: $active-color;
} }
} }

View File

@ -27,7 +27,7 @@ describe('DeepSelect', () => {
}); });
expect(wrapper.hasClass('van-deep-select')).to.be.true; expect(wrapper.hasClass('van-deep-select')).to.be.true;
expect(wrapper.hasStyle('height', '44px')).to.be.true; expect(wrapper.hasStyle('height', '44px')).to.be.true;
expect(wrapper.propsData().maxHeight).to.equal(200); expect(wrapper.vm.maxHeight).to.equal(200);
}); });
it('interact with this component', () => { it('interact with this component', () => {

View File

@ -1,311 +0,0 @@
import OrderGoods from 'packages/order-goods';
import { mount } from 'avoriaz';
import { DOMChecker } from '../utils';
const item1 = {
img_url: 'https://img.yzcdn.cn/upload_files/2017/07/02/af5b9f44deaeb68000d7e4a711160c53.jpg',
pay_price: 1050,
title: '商品 A',
num: '1'
};
const item2 = {
points_price: 200,
pay_price: 50,
img_url: 'https://img.yzcdn.cn/upload_files/2017/07/02/e89d56cd92ad8ce3b9d8e1babc3758b6.jpg',
title: '商品 B',
num: '15',
sku: [{ v: '商品SKU1' }, { v: '商品SKU2' }]
};
const item3 = {
pay_price: 50,
img_url: 'https://img.yzcdn.cn/upload_files/2017/07/02/e89d56cd92ad8ce3b9d8e1babc3758b6.jpg',
title: '商品 C',
num: '15',
is_presale: true,
delivery_time: '三天后发货',
show_delivery_time: true,
is_presale: true,
is_present: true,
message: {
'留言1': '留言1内容',
'留言2': 'https://img.yzcdn.cn/upload_files/2017/07/02/e89d56cd92ad8ce3b9d8e1babc3758b6.jpg'
}
};
describe('OrderGoods', () => {
let wrapper;
afterEach(() => {
wrapper && wrapper.destroy();
});
it('default', () => {
wrapper = mount(OrderGoods, {
attachToDocument: true,
propsData: {
shopName: '起码运动馆',
price: item1.pay_price,
itemList: [item1],
message: '留言留言'
}
});
DOMChecker(wrapper, {
text: {
'.van-order-goods-header a': '起码运动馆',
'.van-order-goods-price .van-cell__value span': '¥10.50',
'.van-card__title': item1.title,
'.van-card__num': 'x ' + item1.num,
'.van-card__price': '¥10.50'
},
value: {
'.van-order-goods-message textarea': '留言留言'
},
src: {
'.van-card__thumb img': item1.img_url
}
});
});
it('empty list', () => {
wrapper = mount(OrderGoods, {
attachToDocument: true,
propsData: {
itemList: []
}
});
const submitSpyFunc = sinon.spy();
wrapper.vm.$on('clickEmptyButton', submitSpyFunc);
wrapper.find('.van-button')[0].trigger('click');
DOMChecker(wrapper, {
text: {
'.van-order-goods-empty p': '当前没有可购买的商品,请重新选择',
'.van-order-goods-empty button': '返回重新选择'
},
src: {
'.van-order-goods-empty img': 'http://b.yzcdn.cn/v2/image/wap/trade/new_order/empty@2x.png'
}
});
expect(submitSpyFunc.calledOnce).to.be.true;
});
it('empty list config', () => {
wrapper = mount(OrderGoods, {
attachToDocument: true,
propsData: {
emptyIcon: 'https://img.yzcdn.cn/upload_files/2017/07/01/FlIeRrn5bMRoWhcwp4Dp1TmVAXKy.jpg',
emptyMessage: '测试',
emptyButtonText: '测试'
}
});
DOMChecker(wrapper, {
text: {
'.van-order-goods-empty p': '测试',
'.van-order-goods-empty button': '测试'
},
src: {
'.van-order-goods-empty img': 'https://img.yzcdn.cn/upload_files/2017/07/01/FlIeRrn5bMRoWhcwp4Dp1TmVAXKy.jpg'
}
});
});
it('edit message', (done) => {
wrapper = mount(OrderGoods, {
attachToDocument: true,
propsData: {
itemList: [item1],
message: ''
}
});
wrapper.vm.$on('input', val => {
wrapper.vm.message = val;
expect(wrapper.vm.message).to.equal('测试留言');
done();
});
const textarea = wrapper.find('textarea')[0];
textarea.element.value = '测试留言';
textarea.trigger('input');
});
it('message not editable', () => {
wrapper = mount(OrderGoods, {
attachToDocument: true,
propsData: {
itemList: [item1],
message: '留言留言',
messageEditable: false
}
});
DOMChecker(wrapper, {
text: {
'.van-order-goods-message p': '留言留言'
}
});
});
it('message not editable && empty', () => {
wrapper = mount(OrderGoods, {
attachToDocument: true,
propsData: {
itemList: [item1],
message: '',
messageEditable: false
}
});
DOMChecker(wrapper, {
text: {
'.van-order-goods-message p': ''
}
});
});
it('points props', () => {
wrapper = mount(OrderGoods, {
attachToDocument: true,
propsData: {
itemList: [item1],
points: 100
}
});
DOMChecker(wrapper, {
text: {
'.van-order-goods-price .van-cell__value span': '100积分'
}
});
});
it('points prop and price prop', () => {
wrapper = mount(OrderGoods, {
attachToDocument: true,
propsData: {
itemList: [item1],
points: 100,
price: 1050
}
});
DOMChecker(wrapper, {
text: {
'.van-order-goods-price .van-cell__value span': '100积分 + ¥10.50'
}
});
});
it('shopLink prop', () => {
wrapper = mount(OrderGoods, {
attachToDocument: true,
propsData: {
itemList: [item1],
shopLink: 'http://www.youzan.com'
}
});
expect(wrapper.find('.van-order-goods-header a')[0].element.getAttribute('href')).to.equal('http://www.youzan.com');
});
it('item with points', () => {
wrapper = mount(OrderGoods, {
attachToDocument: true,
propsData: {
itemList: [item2]
}
});
DOMChecker(wrapper, {
text: {
'.van-card__price': '200积分 + ¥0.50',
'.van-card__title': item2.title,
'.van-card__num': 'x ' + item2.num
},
src: {
'.van-card__thumb img': item2.img_url
}
});
});
it('presable item with deliveryTime', () => {
wrapper = mount(OrderGoods, {
attachToDocument: true,
propsData: {
itemList: [item3]
}
});
DOMChecker(wrapper, {
text: {
'.van-card__price': '¥0.50',
'.van-card__title': item3.title,
'.van-card__num': 'x ' + item3.num,
'.van-order-goods-card__delivery .van-cell__value span': item3.delivery_time
},
count: {
'.van-order-goods-card__present': 1,
'.van-order-goods-card__tag-green': 1
},
src: {
'.van-card__thumb img': item3.img_url
}
});
});
it('item with message', (done) => {
wrapper = mount(OrderGoods, {
attachToDocument: true,
propsData: {
itemList: [item3]
}
});
DOMChecker(wrapper, {
count: {
'.van-order-goods-card__message-button': 1,
'.van-order-goods-card__message li': 2
},
style: {
'.van-order-goods-card__message': {
'display': 'none'
}
}
});
const messageButton = wrapper.find('.van-order-goods-card__message-button')[0];
messageButton.trigger('click');
setTimeout(function() {
DOMChecker(wrapper, {
noStyle: {
'.van-order-goods-card__message': {
'display': 'none'
}
}
});
done();
}, 300);
});
it('multi items', () => {
wrapper = mount(OrderGoods, {
attachToDocument: true,
propsData: {
itemList: [item1, item2, item3]
}
});
DOMChecker(wrapper, {
count: {
'.van-order-goods-card': 3
}
});
});
});

View File

@ -8,7 +8,7 @@ describe('Search', () => {
wrapper && wrapper.destroy(); wrapper && wrapper.destroy();
}); });
it('create a quantity', () => { it('create a stepper', () => {
wrapper = mount(Search); wrapper = mount(Search);
expect(wrapper.hasClass('van-search')).to.be.true; expect(wrapper.hasClass('van-search')).to.be.true;

View File

@ -1,43 +1,43 @@
import Quantity from 'packages/quantity'; import Stepper from 'packages/stepper';
import { mount } from 'avoriaz'; import { mount } from 'avoriaz';
describe('Quantity', () => { describe('Stepper', () => {
let wrapper; let wrapper;
afterEach(() => { afterEach(() => {
wrapper && wrapper.destroy(); wrapper && wrapper.destroy();
}); });
it('create a quantity', () => { it('create a stepper', () => {
wrapper = mount(Quantity, { wrapper = mount(Stepper, {
propsData: { propsData: {
defaultValue: 1 defaultValue: 1
} }
}); });
expect(wrapper.hasClass('van-quantity')).to.be.true; expect(wrapper.hasClass('van-stepper')).to.be.true;
expect(wrapper.data().currentValue).to.equal(1); expect(wrapper.data().currentValue).to.equal(1);
const plusButton = wrapper.find('.van-quantity__plus')[0]; const plusButton = wrapper.find('.van-stepper__plus')[0];
plusButton.trigger('click'); plusButton.trigger('click');
expect(wrapper.data().currentValue).to.equal(2); expect(wrapper.data().currentValue).to.equal(2);
const minusButton = wrapper.find('.van-quantity__minus')[0]; const minusButton = wrapper.find('.van-stepper__minus')[0];
minusButton.trigger('click'); minusButton.trigger('click');
expect(wrapper.data().currentValue).to.equal(1); expect(wrapper.data().currentValue).to.equal(1);
}); });
it('create a disabled quantity', (done) => { it('create a disabled stepper', (done) => {
wrapper = mount(Quantity, { wrapper = mount(Stepper, {
propsData: { propsData: {
disabled: true disabled: true
} }
}); });
expect(wrapper.hasClass('van-quantity')).to.be.true; expect(wrapper.hasClass('van-stepper')).to.be.true;
const minusButton = wrapper.find('.van-quantity__minus')[0]; const minusButton = wrapper.find('.van-stepper__minus')[0];
expect(minusButton.hasClass('van-quantity__minus--disabled')).to.be.true; expect(minusButton.hasClass('van-stepper__minus--disabled')).to.be.true;
const eventStub = sinon.stub(wrapper.vm, '$emit'); const eventStub = sinon.stub(wrapper.vm, '$emit');
minusButton.trigger('click'); minusButton.trigger('click');
@ -48,8 +48,8 @@ describe('Quantity', () => {
done(); done();
}); });
const plusButton = wrapper.find('.van-quantity__plus')[0]; const plusButton = wrapper.find('.van-stepper__plus')[0];
expect(plusButton.hasClass('van-quantity__plus--disabled')).to.be.true; expect(plusButton.hasClass('van-stepper__plus--disabled')).to.be.true;
plusButton.trigger('click'); plusButton.trigger('click');
@ -60,14 +60,14 @@ describe('Quantity', () => {
}); });
}); });
it('update quantity value use v-model', (done) => { it('update stepper value use v-model', (done) => {
wrapper = mount(Quantity, { wrapper = mount(Stepper, {
propsData: { propsData: {
value: 1 value: 1
} }
}); });
expect(wrapper.hasClass('van-quantity')).to.be.true; expect(wrapper.hasClass('van-stepper')).to.be.true;
const eventStub = sinon.stub(wrapper.vm, '$emit'); const eventStub = sinon.stub(wrapper.vm, '$emit');
wrapper.vm.value = 2; wrapper.vm.value = 2;
@ -80,14 +80,14 @@ describe('Quantity', () => {
}); });
it('correct value when value is not correct', (done) => { it('correct value when value is not correct', (done) => {
wrapper = mount(Quantity, { wrapper = mount(Stepper, {
propsData: { propsData: {
value: 50, value: 50,
max: 30 max: 30
} }
}); });
expect(wrapper.hasClass('van-quantity')).to.be.true; expect(wrapper.hasClass('van-stepper')).to.be.true;
expect(wrapper.vm.currentValue).to.equal(30); expect(wrapper.vm.currentValue).to.equal(30);
const eventStub = sinon.stub(wrapper.vm, '$emit'); const eventStub = sinon.stub(wrapper.vm, '$emit');
@ -101,13 +101,13 @@ describe('Quantity', () => {
}); });
it('handle when input change', (done) => { it('handle when input change', (done) => {
wrapper = mount(Quantity, { wrapper = mount(Stepper, {
propsData: { propsData: {
value: 1 value: 1
} }
}); });
const input = wrapper.find('.van-quantity__input')[0]; const input = wrapper.find('.van-stepper__input')[0];
input.element.value = 2; input.element.value = 2;
input.trigger('input'); input.trigger('input');