Merge branch 'dev'

This commit is contained in:
niunai 2018-02-08 17:36:44 +08:00
commit 9e8274309a
154 changed files with 3414 additions and 902 deletions

View File

@ -9,7 +9,6 @@ function buildVantEntry() {
const uninstallComponents = [
'Lazyload',
'Waterfall',
'Dialog',
'Toast',
'ImagePreview',
'Locale'

View File

@ -31,6 +31,8 @@ Vue.component('demo-section', DemoSection);
Locale.add({
'zh-CN': {
add: '增加',
decrease: '减少',
red: '红色',
orange: '橙色',
yellow: '黄色',
@ -45,13 +47,19 @@ Locale.add({
search: '搜索',
content: '内容',
custom: '自定义',
username: '用户名',
password: '密码',
loading: '加载状态',
disabled: '禁用状态',
uneditable: '不可编辑',
basicUsage: '基础用法',
advancedUsage: '高级用法'
advancedUsage: '高级用法',
usernamePlaceholder: '请输入用户名',
passwordPlaceholder: '请输入密码'
},
'en-US': {
add: 'Add',
decrease: 'Decrease',
red: 'Red',
orange: 'Orange',
yellow: 'Yellow',
@ -66,10 +74,14 @@ Locale.add({
search: 'Search',
content: 'Content',
custom: 'Custom',
username: 'Username',
password: 'Password',
loading: 'Loading',
disabled: 'Disabled',
uneditable: 'Uneditable',
basicUsage: 'Basic Usage',
advancedUsage: 'Advanced Usage'
advancedUsage: 'Advanced Usage',
usernamePlaceholder: 'Username',
passwordPlaceholder: 'Password'
}
});

View File

@ -31,6 +31,7 @@ export default {
'cell-swipe': asyncWrapper(r => require.ensure([], () => r(componentWrapper(require('./views/cell-swipe'), 'cell-swipe')), 'cell-swipe')),
'cell': asyncWrapper(r => require.ensure([], () => r(componentWrapper(require('./views/cell'), 'cell')), 'cell')),
'checkbox': asyncWrapper(r => require.ensure([], () => r(componentWrapper(require('./views/checkbox'), 'checkbox')), 'checkbox')),
'circle': asyncWrapper(r => require.ensure([], () => r(componentWrapper(require('./views/circle'), 'circle')), 'circle')),
'contact': asyncWrapper(r => require.ensure([], () => r(componentWrapper(require('./views/contact'), 'contact')), 'contact')),
'coupon': asyncWrapper(r => require.ensure([], () => r(componentWrapper(require('./views/coupon'), 'coupon')), 'coupon')),
'datetime-picker': asyncWrapper(r => require.ensure([], () => r(componentWrapper(require('./views/datetime-picker'), 'datetime-picker')), 'datetime-picker')),

View File

@ -366,7 +366,7 @@ export default {
extend: null,
kdt_id: 55,
discount_price: 0,
stock_num: 6,
stock_num: 4,
stock_mode: 0,
is_sell: null,
combin_sku: false,
@ -506,7 +506,7 @@ export default {
alias: '2oml0r0n5vytj',
quota: 15,
is_virtual: '0',
quota_used: 0,
quota_used: 1,
goods_info: {
title: 'Goods Name',
picture: 'https://img.yzcdn.cn/upload_files/2017/03/16/Fs_OMbSFPa183sBwvG_94llUYiLa.jpeg?imageView2/2/w/100/h/100/q/75/format/jpg',

View File

@ -92,6 +92,10 @@ export default {
&--normal {
margin-right: 10px;
}
.van-loading {
margin: 0 18px;
}
}
.van-doc-demo-block {

View File

@ -1,7 +1,7 @@
<template>
<div>
<van-notice-bar>{{ $t('tips') }}</van-notice-bar>
<demo-section>
<van-notice-bar>{{ $t('tips') }}</van-notice-bar>
<demo-block :title="$t('basicUsage')">
<van-cell-swipe :right-width="65" :left-width="65">
<span slot="left">{{ $t('button1') }}</span>

View File

@ -65,8 +65,6 @@ export default {
<style lang="postcss">
.demo-checkbox {
background: #fff;
.van-checkbox {
margin: 10px 0 0 20px;
}

View File

@ -0,0 +1,78 @@
<template>
<demo-section>
<demo-block :title="$t('basicUsage')">
<van-circle
v-model="currentRate1"
:rate="rate"
:speed="100"
size="120px"
:text="currentRate1.toFixed(0) + '%'"
/>
<van-circle
v-model="currentRate2"
color="#13ce66"
fill="#fff"
:rate="rate"
size="120px"
layer-color="#eee"
:speed="100"
:stroke-width="60"
:clockwise="false"
:text="currentRate2.toFixed(0) + '%'"
/>
<div>
<van-button :text="$t('add')" type="primary" size="small" @click="add" />
<van-button :text="$t('decrease')" type="danger" size="small" @click="reduce" />
</div>
</demo-block>
</demo-section>
</template>
<script>
const format = rate => Math.min(Math.max(rate, 0), 100);
export default {
i18n: {
'zh-CN': {
title2: '样式定制'
},
'en-US': {
title2: 'Custom Style'
}
},
data() {
return {
rate: 30,
currentRate1: 0,
currentRate2: 0
};
},
methods: {
add() {
this.rate = format(this.rate + 20);
},
reduce() {
this.rate = format(this.rate - 20);
}
}
};
</script>
<style lang="postcss">
.demo-circle {
.van-circle {
margin-left: 15px;
}
.van-button {
margin: 15px 0 0 10px;
&:first-of-type {
margin-left: 15px;
}
}
}
</style>

View File

@ -8,6 +8,26 @@
<demo-block :title="$t('title2')">
<van-button @click="onClickConfirm">Confirm</van-button>
</demo-block>
<demo-block :title="$t('advancedUsage')">
<van-button @click="show = true">{{ $t('advancedUsage') }}</van-button>
<van-dialog
v-model="show"
@confirm="show = false"
>
<van-field
v-model="username"
:label="$t('username')"
:placeholder="$t('usernamePlaceholder')"
/>
<van-field
v-model="password"
type="password"
:label="$t('password')"
:placeholder="$t('passwordPlaceholder')"
/>
</van-dialog>
</demo-block>
</demo-section>
</template>
@ -26,6 +46,14 @@ export default {
}
},
data() {
return {
show: false,
username: '',
password: ''
};
},
methods: {
onClickAlert() {
Dialog.alert({
@ -52,7 +80,7 @@ export default {
<style lang="postcss">
.demo-dialog {
.van-button {
.van-doc-demo-block > .van-button {
margin: 15px;
}
}

View File

@ -68,13 +68,9 @@ export default {
title3: '禁用输入框',
title4: '错误提示',
title5: '高度自适应',
username: '用户名',
password: '密码',
message: '留言',
phone: '手机号',
phonePlaceholder: '请输入手机号',
usernamePlaceholder: '请输入用户名',
passwordPlaceholder: '请输入密码',
messagePlaceholder: '请输入留言',
inputDisabled: '输入框已禁用',
phoneError: '手机号格式错误'
@ -84,13 +80,9 @@ export default {
title3: 'Disabled',
title4: 'Error info',
title5: 'Auto resize',
username: 'Username',
password: 'Password',
message: 'Message',
phone: 'Phone',
phonePlaceholder: 'Phone',
usernamePlaceholder: 'Username',
passwordPlaceholder: 'Password',
messagePlaceholder: 'Message',
inputDisabled: 'Disabled',
phoneError: 'Invalid phone'

View File

@ -1,18 +1,18 @@
<template>
<demo-section>
<demo-block :title="$t('title1')">
<van-loading type="circle" color="black" />
<van-loading type="circle" color="white" />
<van-loading color="black" />
<van-loading color="white" />
</demo-block>
<demo-block :title="$t('title2')">
<van-loading type="gradient-circle" color="black" />
<van-loading type="gradient-circle" color="white" />
<van-loading type="spinner" color="black" />
<van-loading type="spinner" color="white" />
</demo-block>
<demo-block :title="$t('title3')">
<van-loading type="spinner" color="black" />
<van-loading type="spinner" color="white" />
<van-loading type="circle" color="black" />
<van-loading type="circle" color="white" />
</demo-block>
</demo-section>
</template>
@ -21,14 +21,14 @@
export default {
i18n: {
'zh-CN': {
title1: '单色圆环',
title2: '渐变色圆环',
title3: 'Spinner'
title1: 'Circular',
title2: 'Spinner',
title3: 'Circle'
},
'en-US': {
title1: 'Solid Circle',
title2: 'Gradient Circle',
title3: 'Spinner'
title1: 'Circular',
title2: 'Spinner',
title3: 'Circle'
}
}
};
@ -38,7 +38,13 @@ export default {
.demo-loading {
.van-loading {
display: inline-block;
margin: 10px 0 10px 20px;
margin: 5px 0 5px 20px;
}
.van-loading--white {
padding: 10px;
border-radius: 3px;
background-color: rgba(0, 0, 0, .5);
}
}
</style>

View File

@ -21,6 +21,10 @@
<demo-block :title="$t('title4')">
<van-picker :columns="columns" @change="onChange2" />
</demo-block>
<demo-block :title="$t('loading')">
<van-picker :columns="columns" loading />
</demo-block>
</demo-section>
</template>

View File

@ -1,21 +1,23 @@
<template>
<van-pull-refresh v-model="isLoading">
<demo-section name="pull-refresh" background="#fff">
<demo-section name="pull-refresh">
<van-pull-refresh v-model="isLoading" @refresh="onRefresh">
<demo-block :title="$t('basicUsage')">
<p>{{ $t('text') }}: {{ count }}</p>
</demo-block>
</demo-section>
</van-pull-refresh>
</van-pull-refresh>
</demo-section>
</template>
<script>
export default {
i18n: {
'zh-CN': {
text: '刷新次数'
text: '刷新次数',
success: '刷新成功'
},
'en-US': {
text: 'Refresh Count'
text: 'Refresh Count',
success: 'Refresh success'
}
},
@ -26,15 +28,13 @@ export default {
};
},
watch: {
isLoading() {
if (this.isLoading) {
setTimeout(() => {
Toast('刷新成功');
this.isLoading = false;
this.count++;
}, 500);
}
methods: {
onRefresh() {
setTimeout(() => {
Toast(this.$t('success'));
this.isLoading = false;
this.count++;
}, 500);
}
}
};
@ -42,6 +42,13 @@ export default {
<style lang="postcss">
.demo-pull-refresh {
.van-pull-refresh {
&,
&__track {
height: 100%;
}
}
p {
margin: 10px 0 0 15px;
}

View File

@ -66,8 +66,6 @@ export default {
<style lang="postcss">
.demo-radio {
background: #fff;
.van-radios {
padding: 0 20px;

View File

@ -11,18 +11,38 @@
:quota="$t('sku').quota"
:quota-used="$t('sku').quota_used"
:reset-stepper-on-hide="true"
:reset-selected-sku-on-hide="true"
:disable-stepper-input="true"
@buy-clicked="handleBuyClicked"
@add-cart="handleAddCartClicked"
:message-config="messageConfig"
@buy-clicked="onBuyClicked"
@add-cart="onAddCartClicked"
/>
<van-button type="primary" @click="showBase = true" block>{{ $t('basicUsage') }}</van-button>
</div>
</demo-block>
<demo-block :title="$t('title2')">
<div class="sku-container">
<van-sku
v-model="showStepper"
:sku="$t('sku').sku"
:goods="$t('sku').goods_info"
:goods-id="$t('sku').goods_id"
:hide-stock="$t('sku').sku.hide_stock"
:quota="$t('sku').quota"
:quota-used="$t('sku').quota_used"
:custom-stepper-config="customStepperConfig"
@buy-clicked="onBuyClicked"
@add-cart="onAddCartClicked"
/>
<van-button type="primary" @click="showStepper = true" block>{{ $t('title2') }}</van-button>
</div>
</demo-block>
<demo-block :title="$t('advancedUsage')">
<div class="sku-container">
<van-sku
v-model="showCustomAction"
v-model="showCustom"
:stepper-title="$t('stepperTitle')"
:sku="$t('sku').sku"
:goods="$t('sku').goods_info"
@ -33,18 +53,17 @@
:quota-used="$t('sku').quota_used"
:reset-stepper-on-hide="true"
:initial-sku="initialSku"
@buy-clicked="handleBuyClicked"
@add-cart="handleAddCartClicked"
@buy-clicked="onBuyClicked"
@add-cart="onAddCartClicked"
>
<template slot="sku-messages" />
<template slot="sku-actions" slot-scope="props">
<div class="van-sku-actions">
<van-button bottom-action @click="handlePointClicked">{{ $t('button1') }}</van-button>
<van-button bottom-action @click="onPointClicked">{{ $t('button1') }}</van-button>
<van-button type="primary" bottom-action @click="props.skuEventBus.$emit('sku:buy')">{{ $t('button2') }}</van-button>
</div>
</template>
</van-sku>
<van-button type="primary" @click="showCustomAction = true" block>{{ $t('advancedUsage') }}</van-button>
<van-button type="primary" @click="showCustom = true" block>{{ $t('advancedUsage') }}</van-button>
</div>
</demo-block>
</demo-section>
@ -52,17 +71,20 @@
<script>
import data from '../mock/sku';
import { LIMIT_TYPE } from '../../../packages/sku/constants';
export default {
i18n: {
'zh-CN': {
sku: data['zh-CN'],
title2: '自定义步进器相关配置',
stepperTitle: '我要买',
button1: '积分兑换',
button2: '买买买'
},
'en-US': {
sku: data['en-US'],
title2: 'Custom Stepper Related Config',
stepperTitle: 'Stepper title',
button1: 'Button',
button2: 'Button'
@ -72,22 +94,49 @@ export default {
data() {
return {
showBase: false,
showCustomAction: false,
showCustom: false,
showStepper: false,
initialSku: {
s1: '30349',
s2: '1193'
},
customStepperConfig: {
quotaText: '单次限购100件',
handleOverLimit: (data) => {
const { action, limitType, quota } = data;
if (action === 'minus') {
Toast('至少选择一件商品');
} else if (action === 'plus') {
if (limitType === LIMIT_TYPE.QUOTA_LIMIT) {
Toast(`限购${quota}`);
} else {
Toast('库存不够了~~');
}
}
}
},
messageConfig: {
uploadImg: () => {
return new Promise((resolve) => {
setTimeout(() => resolve('https://img.yzcdn.cn/upload_files/2017/02/21/FjKTOxjVgnUuPmHJRdunvYky9OHP.jpg!100x100.jpg'), 1000);
});
},
uploadMaxSize: 3
}
};
},
methods: {
handleBuyClicked(data) {
onBuyClicked(data) {
Toast(JSON.stringify(data));
},
handleAddCartClicked(data) {
onAddCartClicked(data) {
Toast(JSON.stringify(data));
},
handlePointClicked() {
onPointClicked() {
Toast('积分兑换');
}
}

View File

@ -47,6 +47,17 @@
</van-tab>
</van-tabs>
</demo-block>
<demo-block :title="$t('title7')">
<van-tabs :active="active">
<van-tab v-for="index in 2" :key="index">
<div slot="title">
<van-icon name="more-o" />{{ $t('tab') }}
</div>
{{ $t('content') }} {{ index }}
</van-tab>
</van-tabs>
</demo-block>
</demo-section>
</template>
@ -59,7 +70,8 @@ export default {
title3: '禁用标签',
title4: '样式风格',
title5: '点击事件',
title6: '粘性布局'
title6: '粘性布局',
title7: '自定义标签'
},
'en-US': {
tab: 'Tab ',
@ -68,7 +80,8 @@ export default {
title3: 'Disabled Tab',
title4: 'Card Style',
title5: 'Click Event',
title6: 'Sticky'
title6: 'Sticky',
title7: 'Custom Tab'
}
},
@ -79,12 +92,6 @@ export default {
};
},
mounted() {
setTimeout(() => {
this.active = 3;
}, 1000);
},
methods: {
onClickDisabled() {
Toast('Disabled!');
@ -101,6 +108,11 @@ export default {
.demo-tab {
margin-bottom: 700px;
.van-tab .van-icon {
margin-right: 5px;
vertical-align: -2px;
}
.van-tab__pane {
background-color: #fff;
padding: 20px;

View File

@ -23,6 +23,7 @@
export default {
i18n: {
'zh-CN': {
loading: '加载中',
title1: '文字提示',
title2: '加载提示',
title3: '成功/失败提示',
@ -52,7 +53,7 @@ export default {
},
showLoadingToast() {
Toast.loading({ mask: true });
Toast.loading({ mask: true, message: this.$t('loading') + '...' });
},
showSuccessToast() {

View File

@ -2,7 +2,7 @@
<demo-section>
<demo-block :title="$t('basicUsage')">
<div class="demo-uploader-container">
<van-uploader :after-read="logContent">
<van-uploader :max-size="102400" @oversize="logContent('oversize')">
<van-icon name="photograph" />
</van-uploader>
</div>
@ -10,7 +10,7 @@
<demo-block :title="$t('title2')">
<div class="demo-uploader-container">
<van-uploader :after-read="logContent" accept="image/gif, image/jpeg" multiple>
<van-uploader accept="image/gif, image/jpeg" multiple :max-size="36000" @oversize="logContent">
<van-icon name="photograph" />
</van-uploader>
</div>

View File

@ -61,6 +61,7 @@ Actionsheet will get another style if there is a `title` prop.
| cancel-text | Text of cancel button | `String` | - | - |
| overlay | Whether to show overlay | `Boolean` | - | - |
| close-on-click-overlay | Whether to close when click overlay | `Boolean` | - | - |
| get-container | Return the mount node for actionsheet | `Function` | - | `() => HTMLElement` |
### Data struct of actions

View File

@ -77,6 +77,12 @@ export default {
| delete | Triggered when click delete | contentForm content |
| change-detail | Triggered when address detail changed | value: address detail |
### Slot
| Name | Description |
|-----------|-----------|
| - | Custom content below postal |
### Data Structure
#### addressInfo Data Structure

View File

@ -44,6 +44,9 @@ Set `columns-num` with 2, you'll have a 2 level picker.
| title | Toolbar title | `String` | `''` | - |
| area-list | an object contains these properties: `province_list`, `city_list` and `county_list` | `Object` | - | - |
| columns-num | level of picker | `String`,`Number` | 3 | - |
| item-height | Option height | `Number` | `44` | - |
| loading | Whether to show loading prompt | `Boolean` | `false` | - |
| visible-item-count | Count of visible columns | `Number` | `5` | - |
### Event

View File

@ -69,6 +69,7 @@ Use `tag` prop to custom button tag
|-----------|-----------|-----------|-------------|-------------|
| type | Type | `String` | `default` | `primary` `danger` |
| size | Size | `String` | `normal` | `large` `small` `mini` |
| text | Text | `String` | - | - |
| tag | Tag | `String` | `button` | - |
| native-type | Native Type Attribute | `String` | `''` | - |
| disabled | Whether disable button | `Boolean` | `false` | - |

View File

@ -4,8 +4,7 @@
``` javascript
import { Cell, CellGroup } from 'vant';
Vue.use(Cell);
Vue.use(CellGroup);
Vue.use(Cell).use(CellGroup);
```
### Usage

View File

@ -1,5 +1,78 @@
## Changelog
### [0.12.8](https://github.com/youzan/vant/tree/v0.12.8)
`2018-02-07`
**Improvements**
* add Circle component [\#608](https://github.com/youzan/vant/pull/608) [@chenjiahan](https://github.com/chenjiahan)
* Tab: add title slot [\#603](https://github.com/youzan/vant/pull/603) [@chenjiahan](https://github.com/chenjiahan)
* Toast: adjust background color [\#601](https://github.com/youzan/vant/pull/601) [@chenjiahan](https://github.com/chenjiahan)
* Popup: support getContaienr [\#611](https://github.com/youzan/vant/pull/611) [@chenjiahan](https://github.com/chenjiahan)
* Sku: support imgage upload [\#612](https://github.com/youzan/vant/pull/612) [@w91](https://github.com/w91)
* Sku: support custom stepper [\#600](https://github.com/youzan/vant/pull/600) [@w91](https://github.com/w91)
**Bug Fixes**
* fix Picker style error in some andriod devices [\#609](https://github.com/youzan/vant/pull/609) [@chenjiahan](https://github.com/chenjiahan)
* fix TreeSelect arrow position error [\#605](https://github.com/youzan/vant/pull/605) [@chenjiahan](https://github.com/chenjiahan)
### [0.12.7](https://github.com/youzan/vant/tree/v0.12.7)
`2018-01-31`
**Improvements**
* Area: add item-height & visible-item-count props [\#591](https://github.com/youzan/vant/pull/591) [@chenjiahan](https://github.com/chenjiahan)
* Dialog: support component call [\#593](https://github.com/youzan/vant/pull/593) [@chenjiahan](https://github.com/chenjiahan)
* Toast: support multiple instance [\#586](https://github.com/youzan/vant/pull/586) [@chenjiahan](https://github.com/chenjiahan)
* Sku: add getSkuData method [\#585](https://github.com/youzan/vant/pull/585) [@chenjiahan](https://github.com/chenjiahan)
**Bug Fixes**
* fix Field multi line label style error [\#583](https://github.com/youzan/vant/pull/583) [@chenjiahan](https://github.com/chenjiahan)
### [0.12.6](https://github.com/youzan/vant/tree/v0.12.6)
`2018-01-25`
**Improvements**
* AddressEdit: add default slot [\#573](https://github.com/youzan/vant/pull/573) [@chenjiahan](https://github.com/chenjiahan)
* Uploader: support maxSize prop [\#575](https://github.com/youzan/vant/pull/575) [@chenjiahan](https://github.com/chenjiahan)
* Sku: add sku-body-top slot and resetSelectedSkuOnHide prop [\#568](https://github.com/youzan/vant/pull/568) [@w91](https://github.com/w91)
**Bug Fixes**
* fix Sku message error when overlimit [\#568](https://github.com/youzan/vant/pull/568) [@w91](https://github.com/w91)
* fix Toast work break [\#567](https://github.com/youzan/vant/pull/567) [@chenjiahan](https://github.com/chenjiahan)
* fix Tab active not work [\#572](https://github.com/youzan/vant/pull/572) [@chenjiahan](https://github.com/chenjiahan)
### [0.12.5](https://github.com/youzan/vant/tree/v0.12.5)
`2018-01-23`
**Improvements**
* Button: add text prop [\#563](https://github.com/youzan/vant/pull/563) [@chenjiahan](https://github.com/chenjiahan)
* CouponList: support v-model、exchangeButtonLoading、exchangeMinLength [\#556](https://github.com/youzan/vant/pull/556) [\#566](https://github.com/youzan/vant/pull/566) [@chenjiahan](https://github.com/chenjiahan)
* Icon: update share icon [\#562](https://github.com/youzan/vant/pull/562) [@chenjiahan](https://github.com/chenjiahan)
* Sku: improve render performance [\#550](https://github.com/youzan/vant/pull/550) [@chenjiahan](https://github.com/chenjiahan)
**Bug Fixes**
* Area: should not display city & county list when not select province [\#560](https://github.com/youzan/vant/pull/560) [@chenjiahan](https://github.com/chenjiahan)
* Cell: fix required style [\#553](https://github.com/youzan/vant/pull/553) [@qianzhaoy](https://github.com/qianzhaoy)
### [0.12.4](https://github.com/youzan/vant/tree/v0.12.4)
`2018-01-18`
**Improvements**
* Picker: add props to custom button text [\#548](https://github.com/youzan/vant/pull/548) [@chenjiahan](https://github.com/chenjiahan)
* Toast: add setDefaultOptions method [\#541](https://github.com/youzan/vant/pull/541) [@chenjiahan](https://github.com/chenjiahan)
* Dialog: add setDefaultOptions method [\#539](https://github.com/youzan/vant/pull/539) [@chenjiahan](https://github.com/chenjiahan)
**Bug Fixes**
* Stepper: not fire event on changing the value prop [\#546](https://github.com/youzan/vant/pull/546) [@chuangbo](https://github.com/chuangbo)
* Picker: fix misspelling of visibleItemCount prop [\#549](https://github.com/youzan/vant/pull/549) [@chenjiahan](https://github.com/chenjiahan)
### [0.12.3](https://github.com/youzan/vant/tree/v0.12.3)
`2018-01-12`

View File

@ -4,8 +4,7 @@
``` javascript
import { Checkbox, CheckboxGroup } from 'vant';
Vue.use(Checkbox);
Vue.use(CheckboxGroup);
Vue.use(Checkbox).use(CheckboxGroup);
```
### Usage

View File

@ -0,0 +1,69 @@
## Circle
### Install
``` javascript
import { Circle } from 'vant';
Vue.use(Circle);
```
### Usage
#### Basic Usage
```html
<van-circle
v-model="currentRate"
:rate="30"
:speed="100"
:text="text"
/>
```
``` javascript
export default {
data() {
return {
currentRate: 0
};
},
computed: {
text() {
return this.currentRate.toFixed(0) + '%'
}
}
};
```
#### Custom style
```html
<van-circle
v-model="currentRate"
color="#13ce66"
fill="#fff"
size="120px"
layer-color="#eee"
:text="text"
:rate="rate"
:speed="100"
:clockwise="false"
:stroke-width="60"
/>
```
### API
| Attribute | Description | Type | Default | Accepted Values |
|-----------|-----------|-----------|-------------|-------------|
| v-model | Current rate | `Number` | - | - |
| rate | Target rate | `Number` | `100` | - |
| size | Circle size | `String` | `100px` | - |
| color | Progress bar color | `String` | `#38f` | - |
| layer-color | Layer color | `String` | `#fff` | - |
| fill | Fill color | `String` | `none` | - |
| speed | Animate speedrate/s| `Number` | - | - |
| text | Text | `String` | - | - |
| stroke-width | Stroke width | `Number` | `40` | - |
| clockwise | Is clockwise | `Boolean` | `true` | - |

View File

@ -4,9 +4,10 @@
``` javascript
import { ContactCard, ContactList, ContactEdit } from 'vant';
Vue.use(ContactCard);
Vue.use(ContactList);
Vue.use(ContactEdit);
Vue
.use(ContactCard)
.use(ContactList)
.use(ContactEdit);
```
### Usage

View File

@ -4,8 +4,7 @@
``` javascript
import { CouponCell, CouponList } from 'vant';
Vue.use(CouponCell);
Vue.use(CouponList);
Vue.use(CouponCell).use(CouponList);
```
### Usage
@ -79,11 +78,14 @@ export default {
| Attribute | Description | Type | Default | Accepted Values |
|-----------|-----------|-----------|-------------|-------------|
| v-model | Current exchange code | `String` | - | - |
| chosen-coupon | Index of chosen coupon | `Number` | `-1` | - |
| coupons | Coupon list | `Array` | `[]` | - |
| disabled-coupons | Disabled voupon list | `Array` | `[]` | - |
| exchange-button-text | Exchange button text | `String` | `Exchange` | - |
| exchange-button-loading | Whether to show loading in exchange button | `Boolean` | `false` | - |
| exchange-button-disabled | Whether to disable exchange button | `Boolean` | `false` | - |
| exchange-min-length | Min length to enable exchange button | `Number` | `1` | - |
| displayed-coupon-index | Index of displayed coupon | `Number` | - | - |
| close-button-text | Close button text | `String` | `Close` | - |
| disabled-list-title | Disabled list title | `String` | `Unavailable` | - |

View File

@ -77,3 +77,64 @@ export default {
| overlay | Whether to show overlay | `Boolean` | `true` | - |
| closeOnClickOverlay | Whether to close when click overlay | `Boolean` | `false` | - |
| lockOnScroll | Whether to lock body scroll | `Boolean` | `true` | - |
#### Advanced Usage
If you need to render vue components within a dialog, you can use dialog component.
```html
<van-dialog v-model="show" @confirm="onConfirm">
<van-field
v-model="username"
label="Username"
placeholder="Username"
/>
<van-field
v-model="password"
type="password"
:label="Password"
:placeholder="Password"
/>
</van-dialog>
```
```js
Vue.use(Dialog);
export default {
data() {
return {
show: false,
username: '',
password: ''
};
},
methods: {
onConfirm() {
this.show = false;
}
}
}
```
### API
| Attribute | Description | Type | Default | Accepted Values |
|-----------|-----------|-----------|-------------|-------------|
| v-model | Whether to show dialog | `Boolean` | - | - |
| title | Title | `String` | - | - |
| message | Message | `String` | - | - |
| show-confirm-button | Whether to show confirm button | `Boolean` | `true` | - |
| show-cancel-button | Whether to show cancel button | `Boolean` | `false` | - |
| confirm-button-text | Confirm button text | `String` | `Confirm` | - |
| cancel-button-text | Cancel button test | `String` | `Cancel` | - |
| overlay | Whether to show overlay | `Boolean` | `true` | - |
| close-on-click-overlay | Whether to close when click overlay | `Boolean` | `false` | - |
| lock-on-scroll | Whether to lock body scroll | `Boolean` | `true` | - |
### Event
| Event | Description | Parameters |
|-----------|-----------|-----------|
| confirm | Triggered when click confirm button | - |
| cancel | Triggered when click cancel button | - |

View File

@ -8,9 +8,10 @@ import {
GoodsActionMiniBtn
} from 'vant';
Vue.use(GoodsAction);
Vue.use(GoodsActionBigBtn);
Vue.use(GoodsActionMiniBtn);
Vue
.use(GoodsAction)
.use(GoodsActionBigBtn)
.use(GoodsActionMiniBtn);
```
### Usage

View File

@ -6,8 +6,7 @@ Quickly and easily create layouts with `van-row` and `van-col`
``` javascript
import { Row, Col } from 'vant';
Vue.use(Row);
Vue.use(Col);
Vue.use(Row).use(Col);
```
### Usage

View File

@ -9,18 +9,11 @@ Vue.use(Loading);
### Usage
#### Solid Circle
#### Circular
```html
<van-loading type="circle" color="black" />
<van-loading type="circle" color="white" />
```
#### Gradient Circle
```html
<van-loading type="gradient-circle" color="black" />
<van-loading type="gradient-circle" color="white" />
<van-loading color="black" />
<van-loading color="white" />
```
#### Spinner
@ -30,9 +23,17 @@ Vue.use(Loading);
<van-loading type="spinner" color="white" />
```
#### Circle
```html
<van-loading type="circle" color="black" />
<van-loading type="circle" color="white" />
```
### API
| Attribute | Description | Type | Default | Accepted Values |
|-----------|-----------|-----------|-------------|-------------|
| color | Color | `String` | `black` | `black` `white` |
| type | Type | `String` | `gradient-circle` | `spinner` `circle` |
| type | Type | `String` | `circular` | `spinner` `circle` |
| size | Size | `String` | `30px` | - |

View File

@ -5,8 +5,7 @@ The PasswordInput component is usually used with [NumberKeyboard](#/en-US/compon
``` javascript
import { PasswordInput, NumberKeyboard } from 'vant';
Vue.use(PasswordInput);
Vue.use(NumberKeyboard);
Vue.use(PasswordInput).use(NumberKeyboard);
```
### Usage

View File

@ -114,6 +114,13 @@ export default {
};
```
#### Loading
When Picker columns data is acquired asynchronously, use `loading` prop to show loading prompt
```html
<van-picker :columns="columns" loading />
```
### API
| Attribute | Description | Type | Default | Accepted Values |
@ -121,6 +128,7 @@ export default {
| columns | Columns data | `Array` | `[]` | - |
| show-toolbar | Whether to show toolbar | `Boolean` | `false` | - |
| title | Toolbar title | `String` | `''` | - |
| loading | Whether to show loading prompt | `Boolean` | `false` | - |
| confirm-button-text | Text of confirm button | `String` | `Confirm` | - |
| cancel-button-text | Text of cancel button | `String` | `Cancel` | - |
| item-height | Option height | `Number` | `44` | - |

View File

@ -48,3 +48,4 @@ Use `position` prop to set popup display position
| close-on-click-overlay | Close popup when click overlay | `Boolean` | `true` | - |
| transition | Transition | `String` | `popup-slide` | - |
| prevent-scroll | Prevent background scroll | `Boolean` | `false` | - |
| get-container | Return the mount node for Popup | `Function` | - | `() => HTMLElement` |

View File

@ -9,14 +9,11 @@ Vue.use(PullRefresh);
### Usage
#### Basic Usage
The `refresh` event will be triggered when pull refresh, you should set `v-model` to `false` to reset loading status after process refresh event.
```html
<!-- use v-model to control loading status -->
<van-pull-refresh
v-model="isLoading"
pulling-text="Pull to refresh..."
loosing-text="Loose to refresh..."
loading-text="Loading..."
>
<van-pull-refresh v-model="isLoading" @refresh="onRefresh">
<p>Refresh Count: {{ count }}</p>
</van-pull-refresh>
```
@ -30,15 +27,13 @@ export default {
}
},
watch: {
isLoading() {
if (this.isLoading) {
setTimeout(() => {
Toast('Refresh Success');
this.isLoading = false;
this.count++;
}, 500);
}
methods: {
onRefresh() {
setTimeout(() => {
this.$toast('Refresh Success');
this.isLoading = false;
this.count++;
}, 500);
}
}
}
@ -49,12 +44,19 @@ export default {
| Attribute | Description | Type | Default | Accepted Values |
|-----------|-----------|-----------|-------------|-------------|
| v-model | Loading status | `Boolean` | - | - |
| pulling-text | Text to show when pulling | `String` | `下拉即可刷新...` | - |
| loosing-text | Text to show when loosing | `String` | `释放即可刷新...` | - |
| loading-text | Text to show when loading | `String` | `加载中...` | - |
| pulling-text | Text to show when pulling | `String` | `Pull to refresh...` | - |
| loosing-text | Text to show when loosing | `String` | `Loose to refresh...` | - |
| loading-text | Text to show when loading | `String` | `Loading...` | - |
| animation-duration | Animation duration | `Number` | `300` | - |
| head-height | Height of head | `Number` | `50` | - |
### Event
| Event | Description | Parameters |
|-----------|-----------|-----------|
| refresh | Triggered when pull refresh | - |
### Slot
| name | Description |

View File

@ -20,9 +20,28 @@ Vue.use(Sku);
:quota="quota"
:quota-used="quotaUsed"
:reset-stepper-on-hide="resetStepperOnHide"
:reset-selected-sku-on-hide="resetSelectedSkuOnHide"
:disable-stepper-input="disableStepperInput"
@buy-clicked="handleBuyClicked"
@add-cart="handleAddCartClicked"
:message-config="messageConfig"
@buy-clicked="onBuyClicked"
@add-cart="onAddCartClicked"
/>
```
#### Custom Stepper Config
```html
<van-sku
v-model="showBase"
:sku="sku"
:goods="goods"
:goods-id="goodsId"
:hide-stock="sku.hide_stock"
:quota="quota"
:quota-used="quotaUsed"
:custom-stepper-config="customStepperConfig"
@buy-clicked="onBuyClicked"
@add-cart="onAddCartClicked"
/>
```
@ -41,15 +60,13 @@ Vue.use(Sku);
:quota-used="quotaUsed"
:reset-stepper-on-hide="true"
:initial-sku="initialSku"
@buy-clicked="handleBuyClicked"
@add-cart="handleAddCartClicked"
@buy-clicked="onBuyClicked"
@add-cart="onAddCartClicked"
>
<!-- hide sku messages -->
<template slot="sku-messages"></template>
<!-- custom sku actions -->
<template slot="sku-actions" slot-scope="props">
<div class="van-sku-actions">
<van-button bottom-action @click="handlePointClicked">Button</van-button>
<van-button bottom-action @click="onPointClicked">Button</van-button>
<!-- trigger sku inner event -->
<van-button type="primary" bottom-action @click="props.skuEventBus.$emit('sku:buy')">Button</van-button>
</div>
@ -70,8 +87,12 @@ Vue.use(Sku);
| quota | Quota (0 as no limit) | `Number` | `0` | - |
| quota-used | Used quota | `Number` | `0` | - |
| reset-stepper-on-hide | Whether to reset stepper when hide | `Boolean` | `false` | - |
| reset-selected-sku-on-hide | Whether to reset selected sku when hide | `Boolean` | `false` | - |
| disable-stepper-input | Whether to disable stepper input | `Boolean` | `false` | - |
| stepper-title | Quantity title | `String` | `Quantity` | - |
| custom-stepper-config | Custom stepper related config | `Object` | `{}` | - |
| message-config | Message related config | `Object` | `{}` | - |
| get-container | Return the mount node for sku | `Function` | - | `() => HTMLElement` |
### Event
@ -80,11 +101,18 @@ Vue.use(Sku);
| add-cart | Triggered when click cart button | data: Object |
| buy-clicked | Triggered when click buy button | data: Object |
### Methods
| Method | Description |
|-----------|-----------|
| getSkuData() | Get current sku data |
### Slot
| Name | Description |
|-----------|-----------|
| sku-header | Custom header |
| sku-body-top | Custom content before sku-group |
| sku-group | Custom sku |
| extra-sku-group | Extra custom content |
| sku-stepper | Custom stepper |
@ -149,6 +177,52 @@ goods: {
}
```
#### customStepperConfig Data Structure
```javascript
customStepperConfig: {
// custom quota text
quotaText: 'only 5 can buy',
// custom callback when over limit
handleOverLimit: (data) => {
const { action, limitType, quota, quotaUsed } = data;
if (action === 'minus') {
Toast('at least select one');
} else if (action === 'plus') {
// const { LIMIT_TYPE } = Sku.skuConstants;
if (limitType === LIMIT_TYPE.QUOTA_LIMIT) {
let msg = `Buy up to ${quota}`;
if (quotaUsed > 0) msg += `you already buy ${quotaUsed}`;
Toast(msg);
} else {
Toast('not enough stock');
}
}
}
}
```
#### messageConfig Data Structure
```javascript
messageConfig: {
// the upload image callback
uploadImg: () => {
return new Promise((resolve) => {
setTimeout(() => resolve('https://img.yzcdn.cn/upload_files/2017/02/21/FjKTOxjVgnUuPmHJRdunvYky9OHP.jpg!100x100.jpg'), 1000);
});
},
// max file size (MB)
uploadMaxSize: 3,
// placehold config
placeholderMap: {
text: 'xxx',
tel: 'xxx',
...
}
}
```
#### Event Params Data Structure
```javascript

View File

@ -4,8 +4,7 @@
``` javascript
import { Step, Steps } from 'vant';
Vue.use(Step);
Vue.use(Steps);
Vue.use(Step).use(Steps);
```
### Usage

View File

@ -4,8 +4,7 @@
``` javascript
import { Swipe, SwipeItem } from 'vant';
Vue.use(Swipe);
Vue.use(SwipeItem);
Vue.use(Swipe).use(SwipeItem);
```
### Usage

View File

@ -4,8 +4,7 @@
``` javascript
import { Tab, Tabs } from 'vant';
Vue.use(Tab);
Vue.use(Tabs);
Vue.use(Tab).use(Tabs);
```
### Usage
@ -105,8 +104,22 @@ In sticky mode, the tab will be fixed to top when scroll to top
```html
<van-tabs :active="active" sticky>
<van-tab v-for="index in 4" :title="'选项 ' + index">
内容 {{ index }}
<van-tab v-for="index in 4" :title="'tab ' + index">
content {{ index }}
</van-tab>
</van-tabs>
```
#### Custom title
Use title slot to custom tab title
```html
<van-tabs :active="active">
<van-tab v-for="index in 2">
<div slot="title">
<van-icon name="more-o" />tab
</div>
content {{ index }}
</van-tab>
</van-tabs>
```
@ -127,6 +140,13 @@ In sticky mode, the tab will be fixed to top when scroll to top
| title | Tab title | `String` | - | - |
| disabled | Whether disabled current tab | `Boolean` | `false` | - |
### Tab Slot
| name | Description |
|-----------|-----------|
| - | Content |
| title | Custom tab |
### Tabs Event
| Event | Description | Arguments |

View File

@ -4,8 +4,7 @@
``` javascript
import { Tabbar, TabbarItem } from 'vant';
Vue.use(Tabbar);
Vue.use(TabbarItem);
Vue.use(Tabbar).use(TabbarItem);
```
### Usage

View File

@ -18,7 +18,10 @@ Toast('Some messages');
#### Loading
```javascript
Toast.loading({ mask: true });
Toast.loading({
mask: true,
message: 'Loading...'
});
```
@ -62,6 +65,19 @@ export default {
}
```
#### Singleton
Toast use singleton mode by default, if you need to pop multiple Toast at the same time, you can refer to the following example
```js
Toast.allowMultiple();
const toast1 = Toast('First Toast');
const toast2 = Toast.success('Second Toast');
toast1.clear();
toast2.clear();
```
### Methods
| Methods | Attribute | Return value | Description |
@ -70,9 +86,10 @@ export default {
| Toast.loading | `options | message` | toast instance | Show loading toast |
| Toast.success | `options | message` | toast instance | Show success toast |
| Toast.fail | `options | message` | toast instance | Show fail toast |
| Toast.clear | `clearAll` | `void` | Close |
| Toast.allowMultiple | - | `void` | Allow multlple toast at the same time |
| Toast.setDefaultOptions | `options` | `void` | Set default options of all toasts |
| Toast.resetDefaultOptions | - | `void` | Reset default options of all toasts |
| Toast.clear | - | `void` | Close |
### Options

View File

@ -42,13 +42,26 @@ You can set native properties such as `accpet`、`multiple` on Uploader, and the
| Attribute | Description | Type | Default | Accepted Values |
|-----------|-----------|-----------|-------------|-------------|
| result-type | The way to read the file, read as base64; read as text | `String` | `dataUrl` | `text` |
| disable | Whether to disable the upload, set to true during the image upload to prevent users from clicking this component to upload pictures | `Boolean` | `false` | - |
| before-read | Hook before reading the file, the first parameter is the selected file, return false to stop reading the file | `Function` | - | - |
| after-read | Hook after reading the file, parameter format: { file ,content } | `Function` | - | - |
| result-type | Type of file read result | `String` | `dataUrl` | `text` |
| disable | Whether to disable the upload | `Boolean` | `false` | - |
| before-read | Hook before reading the file, return false to stop reading the file | `Function` | - | - |
| after-read | Hook after reading the file | `Function` | - | - |
| max-size | Max size of file | `Number` | - | - |
### Event
| Event | Description | Arguments |
|-----------|-----------|-----------|
| oversize | Triggered when file size over limit | Same as after-read |
### Slot
| name | Description |
| Name | Description |
|-----------|-----------|
| - | Custom icon |
### afterRead parematers
| Key | Description | Type |
|-----------|-----------|-----------|
| file | file object | `Object` |
| content | file content | `String` |

View File

@ -25,6 +25,7 @@ export default {
'zh-CN/changelog-generated': wrapper(r => require.ensure([], () => r(require('./zh-CN/changelog-generated.md')), 'zh-CN/changelog-generated')),
'zh-CN/changelog': wrapper(r => require.ensure([], () => r(require('./zh-CN/changelog.md')), 'zh-CN/changelog')),
'zh-CN/checkbox': wrapper(r => require.ensure([], () => r(require('./zh-CN/checkbox.md')), 'zh-CN/checkbox')),
'zh-CN/circle': wrapper(r => require.ensure([], () => r(require('./zh-CN/circle.md')), 'zh-CN/circle')),
'zh-CN/contact': wrapper(r => require.ensure([], () => r(require('./zh-CN/contact.md')), 'zh-CN/contact')),
'zh-CN/coupon': wrapper(r => require.ensure([], () => r(require('./zh-CN/coupon.md')), 'zh-CN/coupon')),
'zh-CN/datetime-picker': wrapper(r => require.ensure([], () => r(require('./zh-CN/datetime-picker.md')), 'zh-CN/datetime-picker')),
@ -77,6 +78,7 @@ export default {
'en-US/cell': wrapper(r => require.ensure([], () => r(require('./en-US/cell.md')), 'en-US/cell')),
'en-US/changelog': wrapper(r => require.ensure([], () => r(require('./en-US/changelog.md')), 'en-US/changelog')),
'en-US/checkbox': wrapper(r => require.ensure([], () => r(require('./en-US/checkbox.md')), 'en-US/checkbox')),
'en-US/circle': wrapper(r => require.ensure([], () => r(require('./en-US/circle.md')), 'en-US/circle')),
'en-US/contact': wrapper(r => require.ensure([], () => r(require('./en-US/contact.md')), 'en-US/contact')),
'en-US/coupon': wrapper(r => require.ensure([], () => r(require('./en-US/coupon.md')), 'en-US/coupon')),
'en-US/datetime-picker': wrapper(r => require.ensure([], () => r(require('./en-US/datetime-picker.md')), 'en-US/datetime-picker')),

View File

@ -72,6 +72,7 @@ export default {
| cancel-text | 取消按钮文案 | `String` | - | - |
| overlay | 是否显示遮罩 | `Boolean` | - | - |
| close-on-click-overlay | 点击遮罩是否关闭`Actionsheet` | `Boolean` | - | - |
| get-container | 指定挂载的 HTML 节点 | `Function` | - | `() => HTMLElement` |
### actions

View File

@ -79,6 +79,13 @@ export default {
| change-area | 修改收件地区时触发 | values: 地区信息 |
| change-detail | 修改详细地址时触发 | value: 详细地址内容 |
### Slot
| 名称 | 说明 |
|-----------|-----------|
| - | 在邮政编码下方插入内容 |
### 数据格式
#### addressInfo 数据格式

View File

@ -42,6 +42,9 @@ Vue.use(Area);
| title | 顶部栏标题 | `String` | `''` | - |
| area-list | 省市县数据,格式见下方 | `Object` | - | - |
| columns-num | 省市县显示列数3-省市县2-省市1-省 | `String`,`Number` | `3` | - |
| loading | 是否显示加载状态 | `Boolean` | `false` | - |
| item-height | 选项高度 | `Number` | `44` | - |
| visible-item-count | 可见的选项个数 | `Number` | `5` | - |
### Event

View File

@ -73,8 +73,9 @@ Vue.use(Button);
|-----------|-----------|-----------|-------------|-------------|
| type | 按钮类型 | `String` | `default` | `primary` `danger` |
| size | 按钮尺寸 | `String` | `normal` | `large` `small` `mini` |
| text | 按钮文字 | `String` | - | - |
| tag | 按钮标签 | `String` | `button` | 任意`HTML`标签 |
| native-type | 按钮类型(原生) | `String` | `''` | - |
| native-type | 按钮类型(原生) | `String` | - | - |
| disabled | 是否禁用 | `Boolean` | `false` | - |
| loading | 是否显示为加载状态 | `Boolean` | `false` | - |
| block | 是否为块级元素 | `Boolean` | `false` | - |

View File

@ -52,7 +52,7 @@ Vue.use(Card);
### Slot
| name | 描述 |
| 名称 | 说明 |
|-----------|-----------|
| title | 自定义标题 |
| desc | 自定义描述 |

View File

@ -66,7 +66,7 @@ export default {
### Slot
| name | 描述 |
| 名称 | 说明 |
|-----------|-----------|
| - | 自定义显示内容 |
| left | 左侧滑动内容 |

View File

@ -4,8 +4,7 @@
``` javascript
import { Cell, CellGroup } from 'vant';
Vue.use(Cell);
Vue.use(CellGroup);
Vue.use(Cell).use(CellGroup);
```
### 代码演示
@ -92,7 +91,7 @@ Vue.use(CellGroup);
### Slot
| name | 描述 |
| 名称 | 说明 |
|-----------|-----------|
| - | 自定义显示内容 |
| icon | 自定义`icon` |

View File

@ -1,5 +1,132 @@
## 更新日志
## [v0.12.8](https://github.com/youzan/vant/tree/v0.12.8) (2018-02-07)
[Full Changelog](https://github.com/youzan/vant/compare/v0.12.7...v0.12.8)
**Issue**
- 一些小小提议 [\#616](https://github.com/youzan/vant/issues/616)
- Toast提示显示时间的问题 [\#613](https://github.com/youzan/vant/issues/613)
- CheckboxGroup 里面的chekBox的prop, name的类型效验 [\#610](https://github.com/youzan/vant/issues/610)
- Waterfall 跳转路由触发 [\#607](https://github.com/youzan/vant/issues/607)
- van-tabs 组件 @click事件 只能传入Index吗。是否可把van-tab绑定的item 传入处理。 [\#606](https://github.com/youzan/vant/issues/606)
- Cell 组件title 属性传递数字 0时不显示内容 [\#604](https://github.com/youzan/vant/issues/604)
- QA: questions for your builds-tools [\#602](https://github.com/youzan/vant/issues/602)
- vue开发中报t.\_g is not a function是版本原因 [\#598](https://github.com/youzan/vant/issues/598)
- 使用PostCSS 插件定制主题报错,找不到$poses变量 [\#597](https://github.com/youzan/vant/issues/597)
- 为什么引用的插件在微信编辑器里可以正常使用在手机上Toast的提示成功的对号图片就不显示了 [\#595](https://github.com/youzan/vant/issues/595)
- android\_23 save事件里获取到的中文get请求显示乱码需要转码这个问题我也再看看先看看大家有遇到过没 [\#594](https://github.com/youzan/vant/issues/594)
- 关于Icon图标组件使用本地字体的问题 [\#592](https://github.com/youzan/vant/issues/592)
- tabs组件问题 [\#589](https://github.com/youzan/vant/issues/589)
- 请问Area组件能否定义item-height [\#588](https://github.com/youzan/vant/issues/588)
- waterfall waterfall-offset 瀑布流 阀值 [\#584](https://github.com/youzan/vant/issues/584)
- 关闭sku层后无法获取到skuData [\#580](https://github.com/youzan/vant/issues/580)
- Toast组件能否触发多个 [\#571](https://github.com/youzan/vant/issues/571)
**Improvements**
- \[new feature\] sku组件增加图片上传功能 [\#612](https://github.com/youzan/vant/pull/612) ([w91](https://github.com/w91))
- \[new feature\] Popup: support getContaienr [\#611](https://github.com/youzan/vant/pull/611) ([chenjiahan](https://github.com/chenjiahan))
- \[bugfix\] Picker: style error in some andriod devices [\#609](https://github.com/youzan/vant/pull/609) ([chenjiahan](https://github.com/chenjiahan))
- \[new feature\] add Circle component [\#608](https://github.com/youzan/vant/pull/608) ([chenjiahan](https://github.com/chenjiahan))
- \[bugfix\] TreeSelect: arrow position error [\#605](https://github.com/youzan/vant/pull/605) ([chenjiahan](https://github.com/chenjiahan))
- \[Improvement\] Tab: add title slot [\#603](https://github.com/youzan/vant/pull/603) ([chenjiahan](https://github.com/chenjiahan))
- \[Improvement\] Toast: adjust background color [\#601](https://github.com/youzan/vant/pull/601) ([chenjiahan](https://github.com/chenjiahan))
- \[new feature\] sku组件增加步进器相关自定义配置 [\#600](https://github.com/youzan/vant/pull/600) ([w91](https://github.com/w91))
## [v0.12.7](https://github.com/youzan/vant/tree/v0.12.7) (2018-01-31)
[Full Changelog](https://github.com/youzan/vant/compare/v0.12.6...v0.12.7)
**Breaking changes**
- 关于上传组件的一些功能扩展 [\#526](https://github.com/youzan/vant/issues/526)
**Issue**
- 业务组件比如地址编辑,按钮文本支持修改吗?(比如保存改成提交) [\#590](https://github.com/youzan/vant/issues/590)
- \[求教\] Dialog.alert 的message可以是tab组件吗? [\#587](https://github.com/youzan/vant/issues/587)
- 社区能活跃点吗? [\#582](https://github.com/youzan/vant/issues/582)
- 页面初始化后Toast自动弹出 [\#581](https://github.com/youzan/vant/issues/581)
- \</van-cell-group\>组件嵌套不正确 [\#578](https://github.com/youzan/vant/issues/578)
- Dialog需求prompt功能 [\#577](https://github.com/youzan/vant/issues/577)
- 遍历对象数组动态生成tabactive不起效 [\#569](https://github.com/youzan/vant/issues/569)
- 没有重置Sku下的规格选项 [\#564](https://github.com/youzan/vant/issues/564)
- 地址编辑 如何新增表单项? [\#555](https://github.com/youzan/vant/issues/555)
**Improvements**
- \[new feature\] Dialog: support component call [\#593](https://github.com/youzan/vant/pull/593) ([chenjiahan](https://github.com/chenjiahan))
- \[Improvement\] Area: add item-height & visible-item-count props [\#591](https://github.com/youzan/vant/pull/591) ([chenjiahan](https://github.com/chenjiahan))
- \[new feature\] Toast: support multiple instance [\#586](https://github.com/youzan/vant/pull/586) ([chenjiahan](https://github.com/chenjiahan))
- \[Improvement\] Sku: add getSkuData method [\#585](https://github.com/youzan/vant/pull/585) ([chenjiahan](https://github.com/chenjiahan))
- \[bugfix\] Field: multi line label stye error [\#583](https://github.com/youzan/vant/pull/583) ([chenjiahan](https://github.com/chenjiahan))
## [v0.12.6](https://github.com/youzan/vant/tree/v0.12.6) (2018-01-25)
[Full Changelog](https://github.com/youzan/vant/compare/v0.12.5...v0.12.6)
**Issue**
- 能否去除cell的下边框线 [\#576](https://github.com/youzan/vant/issues/576)
- 地址编辑 areaList 请求后 赋值不可以? [\#570](https://github.com/youzan/vant/issues/570)
**Improvements**
- \[new feature\] Uploader: support maxSize prop [\#575](https://github.com/youzan/vant/pull/575) ([chenjiahan](https://github.com/chenjiahan))
- \[Improvement\] AddressEdit: add default slot [\#573](https://github.com/youzan/vant/pull/573) ([chenjiahan](https://github.com/chenjiahan))
- \[bugfix\] Tab: active not work [\#572](https://github.com/youzan/vant/pull/572) ([chenjiahan](https://github.com/chenjiahan))
- \[bugfix\] 修复限购情况下,未超出限购数时的错误文案显示;\[new feature\] 增加sku-body-top slot\[new feature\] 增加resetSelectedSkuOnHide参数 [\#568](https://github.com/youzan/vant/pull/568) ([w91](https://github.com/w91))
- \[bugfix\] Toast: work break [\#567](https://github.com/youzan/vant/pull/567) ([chenjiahan](https://github.com/chenjiahan))
## [v0.12.5](https://github.com/youzan/vant/tree/v0.12.5) (2018-01-23)
[Full Changelog](https://github.com/youzan/vant/compare/v0.12.4...v0.12.5)
**Issue**
- ssr项目使用时css加载错误 [\#561](https://github.com/youzan/vant/issues/561)
- css加载报错 [\#559](https://github.com/youzan/vant/issues/559)
- tabbar的active手动设置不生效 [\#558](https://github.com/youzan/vant/issues/558)
- 页面手动刷新 tabbar 会 回到起始路由页面对应的 active icon [\#557](https://github.com/youzan/vant/issues/557)
- 轮播图van-swipe 懒加载图片v-lazy 使用报错Failed to resolve directive: lazy [\#554](https://github.com/youzan/vant/issues/554)
- ssr 使用 babel-plugin-import报错 [\#552](https://github.com/youzan/vant/issues/552)
- stepper如何放到cell里面 [\#551](https://github.com/youzan/vant/issues/551)
- DatetimePicker设置每一列可见元素个数visibile-column-count失效 [\#547](https://github.com/youzan/vant/issues/547)
- Toast 和 Dialog 增加全局参数配置 [\#538](https://github.com/youzan/vant/issues/538)
- picker 组件文档 [\#537](https://github.com/youzan/vant/issues/537)
**Improvements**
- \[Improvement\] CouponList: support v-model & exchangeButtonLoading [\#566](https://github.com/youzan/vant/pull/566) ([chenjiahan](https://github.com/chenjiahan))
- \[Improvement\] update dependencies [\#565](https://github.com/youzan/vant/pull/565) ([chenjiahan](https://github.com/chenjiahan))
- \[Improvement\] Button: add text prop [\#563](https://github.com/youzan/vant/pull/563) ([chenjiahan](https://github.com/chenjiahan))
- \[Improvement\] Icon: update share icon [\#562](https://github.com/youzan/vant/pull/562) ([chenjiahan](https://github.com/chenjiahan))
- \[bugfix\] Area: should not display city & county list when not select province [\#560](https://github.com/youzan/vant/pull/560) ([chenjiahan](https://github.com/chenjiahan))
- \[Improvement\] CouponList: add exchangeMinLength prop [\#556](https://github.com/youzan/vant/pull/556) ([chenjiahan](https://github.com/chenjiahan))
- \[bugfix\] Cell: fix required style [\#553](https://github.com/youzan/vant/pull/553) ([qianzhaoy](https://github.com/qianzhaoy))
- \[Improvement\] Sku: improve render performance [\#550](https://github.com/youzan/vant/pull/550) ([chenjiahan](https://github.com/chenjiahan))
## [v0.12.4](https://github.com/youzan/vant/tree/v0.12.4) (2018-01-18)
[Full Changelog](https://github.com/youzan/vant/compare/v0.12.3...v0.12.4)
**Issue**
- \[Stepper\]: should not fire the events on changing the value prop [\#545](https://github.com/youzan/vant/issues/545)
- 有关vant导入所有组件用法示例异常 [\#543](https://github.com/youzan/vant/issues/543)
- 密码输入框组件与数字键盘组件报错 [\#542](https://github.com/youzan/vant/issues/542)
- ImagePreview 组件文档 [\#540](https://github.com/youzan/vant/issues/540)
- 官网文档 Button组件API "disabled" 拼写错误 [\#536](https://github.com/youzan/vant/issues/536)
- TabBar切换颜色没有加深 [\#535](https://github.com/youzan/vant/issues/535)
- 问一个swipe的问题为什么写了img 写上了v-lazy 没效果 [\#534](https://github.com/youzan/vant/issues/534)
- checkbox的全选取消的问题 [\#533](https://github.com/youzan/vant/issues/533)
**Improvements**
- \[bugfix\] Picker: misspelling of visibleItemCount [\#549](https://github.com/youzan/vant/pull/549) ([chenjiahan](https://github.com/chenjiahan))
- \[Improvement\] Picker: add props to custom button text [\#548](https://github.com/youzan/vant/pull/548) ([chenjiahan](https://github.com/chenjiahan))
- \[bug fix\] Stepper: not fire event on changing the value prop [\#546](https://github.com/youzan/vant/pull/546) ([chuangbo](https://github.com/chuangbo))
- \[Doc\] fix misspelling of NumberKeyboard [\#544](https://github.com/youzan/vant/pull/544) ([chenjiahan](https://github.com/chenjiahan))
- \[Improvement\] Toast: add setDefaultOptions method [\#541](https://github.com/youzan/vant/pull/541) ([chenjiahan](https://github.com/chenjiahan))
- \[Improvement\] Dialog: add setDefaultOptions method [\#539](https://github.com/youzan/vant/pull/539) ([chenjiahan](https://github.com/chenjiahan))
## [v0.12.3](https://github.com/youzan/vant/tree/v0.12.3) (2018-01-12)
[Full Changelog](https://github.com/youzan/vant/compare/v0.12.2...v0.12.3)

View File

@ -1,5 +1,79 @@
## 更新日志
### [0.12.8](https://github.com/youzan/vant/tree/v0.12.8)
`2018-02-07`
**Improvements**
* 新增 Circle 组件 [\#608](https://github.com/youzan/vant/pull/608) [@chenjiahan](https://github.com/chenjiahan)
* Tab: 新增 title slot [\#603](https://github.com/youzan/vant/pull/603) [@chenjiahan](https://github.com/chenjiahan)
* Toast: 加深背景色 [\#601](https://github.com/youzan/vant/pull/601) [@chenjiahan](https://github.com/chenjiahan)
* Popup: 新增 getContaienr 属性 [\#611](https://github.com/youzan/vant/pull/611) [@chenjiahan](https://github.com/chenjiahan)
* Sku: 支持图片上传 [\#612](https://github.com/youzan/vant/pull/612) [@w91](https://github.com/w91)
* Sku: 支持自定义 Stepper [\#600](https://github.com/youzan/vant/pull/600) [@w91](https://github.com/w91)
**Bug Fixes**
* 修复 Picker 在部分设备下的样式问题 [\#609](https://github.com/youzan/vant/pull/609) [@chenjiahan](https://github.com/chenjiahan)
* 修复 TreeSelect 箭头位置错误 [\#605](https://github.com/youzan/vant/pull/605) [@chenjiahan](https://github.com/chenjiahan)
### [0.12.7](https://github.com/youzan/vant/tree/v0.12.7)
`2018-01-31`
**Improvements**
* Area: 新增 item-height、visible-item-count 属性 [\#591](https://github.com/youzan/vant/pull/591) [@chenjiahan](https://github.com/chenjiahan)
* Dialog: 支持以组件形式调用 [\#593](https://github.com/youzan/vant/pull/593) [@chenjiahan](https://github.com/chenjiahan)
* Toast: 支持同时弹出多个 Toast [\#586](https://github.com/youzan/vant/pull/586) [@chenjiahan](https://github.com/chenjiahan)
* Sku: 新增 getSkuData 方法 [\#585](https://github.com/youzan/vant/pull/585) [@chenjiahan](https://github.com/chenjiahan)
**Bug Fixes**
* 修复 Field label 多行时样式错误的问题 [\#583](https://github.com/youzan/vant/pull/583) [@chenjiahan](https://github.com/chenjiahan)
### [0.12.6](https://github.com/youzan/vant/tree/v0.12.6)
`2018-01-25`
**Improvements**
- AddressEdit: 增加默认 slot [\#573](https://github.com/youzan/vant/pull/573) [@chenjiahan](https://github.com/chenjiahan)
- Uploader: 新增 maxSize 属性 [\#575](https://github.com/youzan/vant/pull/575) [@chenjiahan](https://github.com/chenjiahan)
- Sku: 新增 sku-body-top slot、resetSelectedSkuOnHide 属性 [\#568](https://github.com/youzan/vant/pull/568) [@w91](https://github.com/w91)
**Bug Fixes**
- 修复 Toast 文案换行 [\#567](https://github.com/youzan/vant/pull/567) [@chenjiahan](https://github.com/chenjiahan)
- 修复 Sku 限购情况下,未超出限购数时的错误文案显示 [\#568](https://github.com/youzan/vant/pull/568) [@w91](https://github.com/w91)
- 修复 Tab active 在初始化时未生效的问题 [\#572](https://github.com/youzan/vant/pull/572) [@chenjiahan](https://github.com/chenjiahan)
### [0.12.5](https://github.com/youzan/vant/tree/v0.12.5)
`2018-01-23`
**Improvements**
* Button: 新增 text 属性 [\#563](https://github.com/youzan/vant/pull/563) [@chenjiahan](https://github.com/chenjiahan)
* CouponList: 支持 v-model、exchangeButtonLoading、exchangeMinLength [\#556](https://github.com/youzan/vant/pull/556) [\#566](https://github.com/youzan/vant/pull/566) [@chenjiahan](https://github.com/chenjiahan)
* Icon: 更新 share 图标 [\#562](https://github.com/youzan/vant/pull/562) [@chenjiahan](https://github.com/chenjiahan)
* Sku: 优化渲染性能 [\#550](https://github.com/youzan/vant/pull/550) [@chenjiahan](https://github.com/chenjiahan)
**Bug Fixes**
* Area: 修复未选中省份时市区展示错误的问题 [\#560](https://github.com/youzan/vant/pull/560) [@chenjiahan](https://github.com/chenjiahan)
* Cell: 修复 required 样式错误的问题 [\#553](https://github.com/youzan/vant/pull/553) [@qianzhaoy](https://github.com/qianzhaoy)
### [0.12.4](https://github.com/youzan/vant/tree/v0.12.4)
`2018-01-18`
**Improvements**
* Picker: 新增 confirmButtonText、cancelButtonText 属性 [\#548](https://github.com/youzan/vant/pull/548) [@chenjiahan](https://github.com/chenjiahan)
* Toast: 新增 setDefaultOptions 方法 [\#541](https://github.com/youzan/vant/pull/541) [@chenjiahan](https://github.com/chenjiahan)
* Dialog: 新增 setDefaultOptions 方法 [\#539](https://github.com/youzan/vant/pull/539) [@chenjiahan](https://github.com/chenjiahan)
**Bug Fixes**
* Stepper: 修改 value 值时不触发 change 事件 [\#546](https://github.com/youzan/vant/pull/546) [@chuangbo](https://github.com/chuangbo)
* Picker: 修复 visibleItemCount 属性拼写错误 [\#549](https://github.com/youzan/vant/pull/549) [@chenjiahan](https://github.com/chenjiahan)
### [0.12.3](https://github.com/youzan/vant/tree/v0.12.3)
`2018-01-12`

View File

@ -4,8 +4,7 @@
``` javascript
import { Checkbox, CheckboxGroup } from 'vant';
Vue.use(Checkbox);
Vue.use(CheckboxGroup);
Vue.use(Checkbox).use(CheckboxGroup);
```
### 代码演示

View File

@ -0,0 +1,70 @@
## Circle 环形进度条
### 使用指南
``` javascript
import { Circle } from 'vant';
Vue.use(Circle);
```
### 代码演示
#### 基础用法
通过 `rate` 指定目标进度,`v-model` 代表当前进度,`speed` 控制动画速度
```html
<van-circle
v-model="currentRate"
:rate="30"
:speed="100"
:text="text"
/>
```
``` javascript
export default {
data() {
return {
currentRate: 0
};
},
computed: {
text() {
return this.currentRate.toFixed(0) + '%'
}
}
};
```
#### 样式定制
```html
<van-circle
v-model="currentRate"
color="#13ce66"
fill="#fff"
size="120px"
layer-color="#eee"
:text="text"
:rate="rate"
:speed="100"
:clockwise="false"
:stroke-width="60"
/>
```
### API
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| v-model | 当前进度 | `Number` | - | - |
| rate | 目标进度 | `Number` | `100` | - |
| size | 圆环直径 | `String` | `100px` | - |
| color | 进度条颜色 | `String` | `#38f` | - |
| layer-color | 轨道颜色 | `String` | `#fff` | - |
| fill | 填充颜色 | `String` | `none` | - |
| speed | 动画速度(单位为 rate/s| `Number` | - | - |
| text | 文字 | `String` | - | - |
| stroke-width | 进度条宽度 | `Number` | `40` | - |
| clockwise | 是否顺时针增加 | `Boolean` | `true` | - |

View File

@ -5,9 +5,10 @@
``` javascript
import { ContactCard, ContactList, ContactEdit } from 'vant';
Vue.use(ContactCard);
Vue.use(ContactList);
Vue.use(ContactEdit);
Vue
.use(ContactCard)
.use(ContactList)
.use(ContactEdit);
```
### 代码演示

View File

@ -4,8 +4,7 @@
``` javascript
import { CouponCell, CouponList } from 'vant';
Vue.use(CouponCell);
Vue.use(CouponList);
Vue.use(CouponCell).use(CouponList);
```
### 代码演示
@ -69,7 +68,7 @@ export default {
### CouponCell API
| 参数 | 说明 | 类型 | 默认值 | 必须 |
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| title | 单元格标题 | `String` | `优惠券码` | - |
| chosen-coupon | 当前选中优惠券的索引 | `Number` | `-1` | - |
@ -78,13 +77,16 @@ export default {
### CouponList API
| 参数 | 说明 | 类型 | 默认值 | 必须 |
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| v-model | 当前输入的兑换码 | `String` | - | - |
| chosen-coupon | 当前选中优惠券的索引 | `Number` | `-1` | - |
| coupons | 可用优惠券列表 | `Array` | `[]` | - |
| disabled-doupons | 不可用优惠券列表 | `Array` | `[]` | - |
| exchange-button-text | 兑换按钮文字 | `String` | `兑换` | - |
| exchange-button-loading | 是否在兑换按钮上显示加载动画 | `Boolean` | `false` | - |
| exchange-button-disabled | 是否禁用兑换按钮 | `Boolean` | `false` | - |
| exchange-min-length | 兑换码最小长度 | `Number` | `1` | - |
| displayed-coupon-index | 滚动至特定优惠券位置 | `Number` | - | - |
| show-close-button | 是否显示列表底部按钮 | `Boolean` | `true` | - |
| close-button-text | 列表底部按钮文字 | `String` | `不使用优惠` | - |

View File

@ -1,4 +1,5 @@
## Dialog 弹出框
Dialog 组件支持函数调用和组件调用两种形式
### 使用指南
@ -40,8 +41,8 @@ Dialog.confirm({
});
```
#### 组件内调用
引入 Dialog 组件后,会自动在 Vue 的 prototype 上挂载 $dialog 方法,便于在组件内调用。
#### 全局方法
引入 Dialog 组件后,会自动在 Vue 的 prototype 上挂载 $dialog 方法,在所有组件内部都可以直接调用此方法
```js
export default {
@ -77,3 +78,65 @@ export default {
| overlay | 是否展示蒙层 | `Boolean` | `true` | - |
| closeOnClickOverlay | 点击蒙层时是否关闭弹窗 | `Boolean` | `false` | - |
| lockOnScroll | 是否禁用背景滚动 | `Boolean` | `true` | - |
#### 高级用法
如果需要在弹窗内实现更复杂的交互,可以通过组件形式来调用 Dialog
```html
<van-dialog v-model="show" @confirm="onConfirm">
<van-field
v-model="username"
label="用户名"
placeholder="请输入用户名"
/>
<van-field
v-model="password"
type="password"
:label="密码"
:placeholder="请输入密码"
/>
</van-dialog>
```
```js
Vue.use(Dialog);
export default {
data() {
return {
show: false,
username: '',
password: ''
};
},
methods: {
onConfirm() {
this.show = false;
}
}
}
```
### API
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| v-model | 是否显示弹窗 | `Boolean` | - | - |
| title | 标题 | `String` | - | - |
| message | 内容 | `String` | - | - |
| show-confirm-button | 是否展示确认按钮 | `Boolean` | `true` | - |
| show-cancel-button | 是否展示取消按钮 | `Boolean` | `false` | - |
| confirm-button-text | 确认按钮的文案 | `String` | `确认` | - |
| cancel-button-text | 取消按钮的文案 | `String` | `取消` | - |
| overlay | 是否展示蒙层 | `Boolean` | `true` | - |
| close-on-click-overlay | 点击蒙层时是否关闭弹窗 | `Boolean` | `false` | - |
| lock-on-scroll | 是否禁用背景滚动 | `Boolean` | `true` | - |
### Event
| 事件 | 说明 | 回调参数 |
|-----------|-----------|-----------|
| confirm | 点击确认按钮时触发 | - |
| cancel | 点击取消按钮时触发 | - |

View File

@ -107,12 +107,12 @@ Filed 默认支持 Input 标签所有的原生属性,比如 `maxlength`、`pla
### Event
Filed 默认支持 Input 标签所有的原生事件,如 `focus``blur``keypress`
| 事件名称 | 说明 | 回调参数 |
| 事件 | 说明 | 回调参数 |
|-----------|-----------|-----------|
| click-icon | 点击尾部图标时触发 | - |
### Slot
| name | 描述 |
| 名称 | 说明 |
|-----------|-----------|
| icon | 自定义icon |

View File

@ -8,9 +8,10 @@ import {
GoodsActionMiniBtn
} from 'vant';
Vue.use(GoodsAction);
Vue.use(GoodsActionBigBtn);
Vue.use(GoodsActionMiniBtn);
Vue
.use(GoodsAction)
.use(GoodsActionBigBtn)
.use(GoodsActionMiniBtn);
```
### 代码演示

View File

@ -6,8 +6,7 @@
``` javascript
import { Row, Col } from 'vant';
Vue.use(Row);
Vue.use(Col);
Vue.use(Row).use(Col);
```
### 代码演示

View File

@ -9,18 +9,11 @@ Vue.use(Loading);
### 代码演示
#### 单色圆环
#### Circular
```html
<van-loading type="circle" color="black" />
<van-loading type="circle" color="white" />
```
#### 渐变色圆环
```html
<van-loading type="gradient-circle" color="black" />
<van-loading type="gradient-circle" color="white" />
<van-loading color="black" />
<van-loading color="white" />
```
#### Spinner
@ -30,9 +23,17 @@ Vue.use(Loading);
<van-loading type="spinner" color="white" />
```
#### Circle
```html
<van-loading type="circle" color="black" />
<van-loading type="circle" color="white" />
```
### API
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| color | 颜色 | `String` | `black` | `black` `white` |
| type | 类型 | `String` | `gradient-circle` | `spinner` `circle` |
| type | 类型 | `String` | `circular` | `spinner` `circle` |
| size | 大小 | `String` | `30px` | - |

View File

@ -57,7 +57,7 @@ export default {
### Slot
| name | 描述 |
| 名称 | 说明 |
|-----------|-----------|
| title | 自定义标题 |
| left | 自定义左侧区域内容 |

View File

@ -41,7 +41,7 @@ Vue.use(Panel);
### Slot
| name | 描述 |
| 名称 | 说明 |
|-----------|-----------|
| - | 自定义内容 |
| header | 自定义 header |

View File

@ -5,8 +5,7 @@
``` javascript
import { PasswordInput, NumberKeyboard } from 'vant';
Vue.use(PasswordInput);
Vue.use(NumberKeyboard);
Vue.use(PasswordInput).use(NumberKeyboard);
```
### 代码演示

View File

@ -116,6 +116,13 @@ export default {
};
```
#### 加载状态
当 Picker 数据是通过异步获取时,可以通过 `loading` 属性显示加载提示
```html
<van-picker :columns="columns" loading />
```
### API
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
@ -123,6 +130,7 @@ export default {
| columns | 对象数组,配置每一列显示的数据 | `Array` | `[]` | - |
| show-toolbar | 是否显示顶部栏 | `Boolean` | `false` | - |
| title | 顶部栏标题 | `String` | `''` | - |
| loading | 是否显示加载状态 | `Boolean` | `false` | - |
| confirm-button-text | 确认按钮文字 | `String` | `完成` | - |
| cancel-button-text | 取消按钮文字 | `String` | `取消` | - |
| item-height | 选项高度 | `Number` | `44` | - |

View File

@ -48,3 +48,4 @@ export default {
| close-on-click-overlay | 点击蒙层是否关闭 Popup | `Boolean` | `true` | - |
| transition | transition 名称 | `String` | `popup-slide` | - |
| prevent-scroll | 是否防止滚动穿透 | `Boolean` | `false` | - |
| get-container | 指定弹出层挂载的 HTML 节点 | `Function` | - | `() => HTMLElement` |

View File

@ -9,9 +9,11 @@ Vue.use(PullRefresh);
### 代码演示
#### 基础用法
下拉刷新时会触发 `refresh` 事件,在事件的回调函数中可以进行同步或异步操作,操作完成后将 `v-model` 设置为 `false`,表示加载完成。
```html
<!-- 通过 v-model 控制加载状态 -->
<van-pull-refresh v-model="isLoading">
<van-pull-refresh v-model="isLoading" @refresh="onRefresh">
<p>刷新次数: {{ count }}</p>
</van-pull-refresh>
```
@ -25,15 +27,13 @@ export default {
}
},
watch: {
isLoading() {
if (this.isLoading) {
setTimeout(() => {
Toast('刷新成功');
this.isLoading = false;
this.count++;
}, 500);
}
methods: {
onRefresh() {
setTimeout(() => {
this.$toast('刷新成功');
this.isLoading = false;
this.count++;
}, 500);
}
}
}
@ -50,9 +50,15 @@ export default {
| animation-duration | 动画时长 | `Number` | `300` | - |
| head-height | 顶部内容高度 | `Number` | `50` | - |
### Event
| 事件名 | 说明 | 参数 |
|-----------|-----------|-----------|
| refresh | 下拉刷新时触发 | - |
### Slot
| name | 描述 |
| 名称 | 说明 |
|-----------|-----------|
| - | 自定义内容 |
| normal | 非下拉状态时顶部内容 |

View File

@ -64,6 +64,6 @@ Search 默认支持 Input 标签所有的原生事件,如 `focus`、`blur`、`
### Slot
| name | 描述 |
| 名称 | 说明 |
|-----------|-----------|
| action | 自定义搜索框右侧按钮,需要在`showAction`为 true 时才会显示 |

View File

@ -20,9 +20,28 @@ Vue.use(Sku);
:quota="quota"
:quota-used="quotaUsed"
:reset-stepper-on-hide="resetStepperOnHide"
:reset-selected-sku-on-hide="resetSelectedSkuOnHide"
:disable-stepper-input="disableStepperInput"
@buy-clicked="handleBuyClicked"
@add-cart="handleAddCartClicked"
:message-config="messageConfig"
@buy-clicked="onBuyClicked"
@add-cart="onAddCartClicked"
/>
```
#### 自定义步进器相关配置
```html
<van-sku
v-model="showBase"
:sku="sku"
:goods="goods"
:goods-id="goodsId"
:hide-stock="sku.hide_stock"
:quota="quota"
:quota-used="quotaUsed"
:custom-stepper-config="customStepperConfig"
@buy-clicked="onBuyClicked"
@add-cart="onAddCartClicked"
/>
```
@ -41,16 +60,14 @@ Vue.use(Sku);
:quota-used="quotaUsed"
:reset-stepper-on-hide="true"
:initial-sku="initialSku"
@buy-clicked="handleBuyClicked"
@add-cart="handleAddCartClicked"
@buy-clicked="onBuyClicked"
@add-cart="onAddCartClicked"
>
<!-- 隐藏 sku messages -->
<template slot="sku-messages"></template>
<!-- 自定义 sku actions -->
<template slot="sku-actions" slot-scope="props">
<div class="van-sku-actions">
<van-button bottom-action @click="handlePointClicked">积分兑换</van-button>
<!-- 直接触发 sku 内部事件,通过内部事件执行 handleBuyClicked 回调 -->
<van-button bottom-action @click="onPointClicked">积分兑换</van-button>
<!-- 直接触发 sku 内部事件,通过内部事件执行 onBuyClicked 回调 -->
<van-button type="primary" bottom-action @click="props.skuEventBus.$emit('sku:buy')">买买买</van-button>
</div>
</template>
@ -71,8 +88,12 @@ Vue.use(Sku);
| quota | 限购数(0表示不限购) | `Number` | `0` | - |
| quota-used | 已经购买过的数量 | `Number` | `0` | - |
| reset-stepper-on-hide | 窗口隐藏时重置选择的商品数量 | `Boolean` | `false` | - |
| reset-selected-sku-on-hide | 窗口隐藏时重置已选择的sku | `Boolean` | `false` | - |
| disable-stepper-input | 是否禁用sku中stepper的input框 | `Boolean` | `false` | - |
| stepper-title | 数量选择组件左侧文案 | `String` | `购买数量` | - |
| custom-stepper-config | 步进器相关自定义配置 | `Object` | `{}` | - |
| message-config | 留言相关配置 | `Object` | `{}` | - |
| get-container | 指定挂载的 HTML 节点 | `Function` | - | `() => HTMLElement` |
### Event
@ -81,6 +102,11 @@ Vue.use(Sku);
| add-cart | 点击添加购物车回调 | skuData: Object |
| buy-clicked | 点击购买回调 | skuData: Object |
### 方法
| 函数 | 说明 |
|-----------|-----------|
| getSkuData() | 获取当前 skuData |
### Slot
Sku 组件默认划分好了若干区块,这些区块都定义成了 slot可以按需进行替换。区块顺序见下表
@ -88,6 +114,7 @@ Sku 组件默认划分好了若干区块,这些区块都定义成了 slot
| 名称 | 说明 |
|-----------|-----------|
| sku-header | 商品信息展示区,包含商品图片、名称、价格等信息 |
| sku-body-top | sku展示区上方的slot无默认展示内容按需使用 |
| sku-group | 商品sku展示区 |
| extra-sku-group | 额外商品sku展示区一般用不到 |
| sku-stepper | 商品数量选择区 |
@ -157,6 +184,51 @@ goods: {
}
```
#### customStepperConfig 对象结构
```javascript
customStepperConfig: {
// 自定义限购文案
quotaText: '每次限购xxx件',
// 自定义步进器超过限制时的回调
handleOverLimit: (data) => {
const { action, limitType, quota, quotaUsed } = data;
if (action === 'minus') {
Toast('至少选择一件商品');
} else if (action === 'plus') {
// const { LIMIT_TYPE } = Sku.skuConstants;
if (limitType === LIMIT_TYPE.QUOTA_LIMIT) {
let msg = `单次限购${quota}件`;
if (quotaUsed > 0) msg += `,您已购买${quotaUsed}`;
Toast(msg);
} else {
Toast('库存不够了~~');
}
}
}
}
```
#### messageConfig Data Structure
```javascript
messageConfig: {
// 图片上传回调需要返回一个promisepromise正确执行的结果需要是一个图片url
uploadImg: () => {
return new Promise((resolve) => {
setTimeout(() => resolve('https://img.yzcdn.cn/upload_files/2017/02/21/FjKTOxjVgnUuPmHJRdunvYky9OHP.jpg!100x100.jpg'), 1000);
});
},
// 最大上传体积 (MB)
uploadMaxSize: 3,
// placehold配置
placeholderMap: {
text: 'xxx',
tel: 'xxx',
...
}
}
```
#### 添加购物车和点击购买回调函数接收的 skuData 对象结构
```javascript
skuData: {

View File

@ -4,8 +4,7 @@
``` javascript
import { Step, Steps } from 'vant';
Vue.use(Step);
Vue.use(Steps);
Vue.use(Step).use(Steps);
```
### 代码演示

View File

@ -80,7 +80,7 @@ Vue.use(SubmitBar);
### Slot
| Name | 说明 |
| 名称 | 说明 |
|-----------|-----------|
| default | 自定义订单栏左侧内容 |
| tip | 提示文案中的额外操作和说明 |

View File

@ -4,8 +4,7 @@
``` javascript
import { Swipe, SwipeItem } from 'vant';
Vue.use(Swipe);
Vue.use(SwipeItem);
Vue.use(Swipe).use(SwipeItem);
```
### 代码演示

View File

@ -4,8 +4,7 @@
``` javascript
import { Tab, Tabs } from 'vant';
Vue.use(Tab);
Vue.use(Tabs);
Vue.use(Tab).use(Tabs);
```
### 代码演示
@ -111,6 +110,20 @@ export default {
</van-tabs>
```
#### 自定义标签
通过 title slot 可以自定义标签内容
```html
<van-tabs :active="active">
<van-tab v-for="index in 2">
<div slot="title">
<van-icon name="more-o" />选项
</div>
内容 {{ index }}
</van-tab>
</van-tabs>
```
### Tabs API
| 参数 | 说明 | 类型 | 默认值 | 可选 |
@ -128,6 +141,13 @@ export default {
| title | tab的标题 | `String` | - | - |
| disabled | 是否禁用这个tab | `Boolean` | `false` | - |
### Tab Slot
| 名称 | 说明 |
|-----------|-----------|
| - | 标签页内容 |
| title | 自定义标签 |
### Tabs Event
| 事件名 | 说明 | 参数 |

View File

@ -4,8 +4,7 @@
``` javascript
import { Tabbar, TabbarItem } from 'vant';
Vue.use(Tabbar);
Vue.use(TabbarItem);
Vue.use(Tabbar).use(TabbarItem);
```
### 代码演示

View File

@ -49,6 +49,6 @@ Vue.use(Tag);
### Slot
| name | 描述 |
| 名称 | 说明 |
|-----------|-----------|
| - | 自定义 Tag 显示内容 |

View File

@ -18,7 +18,10 @@ Toast('我是提示文案,建议不超过十五字~');
#### 加载提示
```javascript
Toast.loading({ mask: true });
Toast.loading({
mask: true,
message: '加载中...'
});
```
@ -62,6 +65,18 @@ export default {
}
```
#### 单例模式
Toast 默认采用单例模式,即同一时间只会存在一个 Toast如果需要在同一时间弹出多个 Toast可以参考下面的示例
```js
Toast.allowMultiple();
const toast1 = Toast('第一个 Toast');
const toast2 = Toast.success('第二个 Toast');
toast1.clear();
toast2.clear();
```
### 方法
@ -72,9 +87,10 @@ export default {
| Toast.loading | `options | message` | toast 实例 | 展示加载提示 |
| Toast.success | `options | message` | toast 实例 | 展示成功提示 |
| Toast.fail | `options | message` | toast 实例 | 展示失败提示 |
| Toast.clear | `clearAll` | `void` | 关闭提示 |
| Toast.allowMultiple | - | `void` | 允许同时存在多个 Toast |
| Toast.setDefaultOptions | `options` | `void` | 修改默认配置,对所有 Toast 生效 |
| Toast.resetDefaultOptions | - | `void` | 重置默认配置,对所有 Toast 生效 |
| Toast.clear | - | `void` | 关闭提示 |
### Options

View File

@ -40,13 +40,26 @@ export default {
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| result-type | 读取文件的方式以base64的方式读取以文本的方式读取 | `String` | `dataUrl` | `text` |
| disable | 是否禁用上传,在图片上传期间设置为true禁止用户点击此组件上传图片 | `Boolean` | `false` | - |
| before-read | 读文件之前的钩子,参数为选择的文件,若返回 false 则停止读取文件 | `Function` | - | - |
| after-read | 文件读完之后回调此函数,参数为 { file:'选择的文件',content:'读的内容' } | `Function` | - | - |
| result-type | 文件读取结果类型 | `String` | `dataUrl` | `text` |
| disable | 是否禁用图片上传 | `Boolean` | `false` | - |
| before-read | 读取前的回调函数,返回 false 可终止文件读取 | `Function` | - | - |
| after-read | 读取完成后的回调函数 | `Function` | - | - |
| max-size | 文件大小限制,单位为 byte | `Number` | - | - |
### Event
| 事件名 | 说明 | 参数 |
|-----------|-----------|-----------|
| oversize | 文件大小超过限制时触发 | 同 after-read |
### Slot
| name | 描述 |
| 名称 | 说明 |
|-----------|-----------|
| - | 自定义上传显示图标 |
| - | 自定义 uploader 内容 |
### afterRead 回调参数
| key | 说明 | 类型 |
|-----------|-----------|-----------|
| file | 文件解析后的 file 对象 | `Object` |
| content | 文件内容 | `String` |

View File

@ -1,7 +1,37 @@
<template>
<router-view />
<div>
<van-nav-bar
v-show="title"
fixed
class="van-doc-nav-bar"
:title="title"
left-arrow
:left-text="$t('back')"
@click-left="onBack"
/>
<router-view />
</div>
</template>
<script>
import { camelize } from 'packages/utils';
export default {
computed: {
title() {
const name = this.$route.name;
return name ? camelize(name.split('/').pop()) : '';
}
},
methods: {
onBack() {
history.back();
}
}
};
</script>
<style lang="postcss">
body {
color: #333;
@ -10,4 +40,14 @@ body {
font-family: Arial, Helvetica, "STHeiti STXihei", "Microsoft YaHei", Tohoma, sans-serif;
-webkit-font-smoothing: antialiased;
}
.van-doc-nav-bar {
.van-nav-bar__title {
text-transform: capitalize;
}
}
.van-doc-demo-section {
padding-top: 46px;
}
</style>

View File

@ -4,7 +4,7 @@ module.exports = {
header: {
logo: {
image: 'https://img.yzcdn.cn/public_files/2017/12/18/fd78cf6bb5d12e2a119d0576bedfd230.png',
title: 'Zan UI',
title: 'Vant',
href: 'http://www.youzanyun.com/zanui'
},
nav: {
@ -80,6 +80,10 @@ module.exports = {
path: '/cell',
title: 'Cell - 单元格'
},
{
path: '/circle',
title: 'Circle - 环形进度条'
},
{
path: '/icon',
title: 'Icon - 图标'
@ -282,7 +286,7 @@ module.exports = {
header: {
logo: {
image: 'https://img.yzcdn.cn/public_files/2017/12/18/fd78cf6bb5d12e2a119d0576bedfd230.png',
title: 'Zan UI',
title: 'Vant',
href: 'http://www.youzanyun.com/zanui'
},
nav: {
@ -358,6 +362,10 @@ module.exports = {
path: '/cell',
title: 'Cell'
},
{
path: '/circle',
title: 'Circle'
},
{
path: '/icon',
title: 'Icon'

View File

@ -9,12 +9,13 @@ import 'packages/vant-css/src/icon-local.css';
import 'vant-doc/src/helper/touch-simulator';
import './components/nprogress.css';
Vue.use(Vant);
Vue.use(VantDoc);
Vue.use(Lazyload, {
lazyComponent: true
});
Vue.use(VueRouter);
Vue
.use(Vant)
.use(VantDoc)
.use(VueRouter)
.use(Lazyload, {
lazyComponent: true
});
const routesConfig = routes(true);
const router = new VueRouter({
@ -23,6 +24,13 @@ const router = new VueRouter({
routes: routesConfig
});
router.afterEach(() => {
if (router.currentRoute.name) {
window.scrollTo(0, 0);
}
Vue.nextTick(() => window.syncPath());
});
window.vueRouter = router;
new Vue({ // eslint-disable-line

View File

@ -6,8 +6,7 @@ import VantDoc from 'vant-doc';
import isMobile from './utils/is-mobile';
import './components/nprogress.css';
Vue.use(VueRouter);
Vue.use(VantDoc);
Vue.use(VueRouter).use(VantDoc);
const routesConfig = routes();

View File

@ -5,6 +5,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<link rel="shortcut icon" href="https://img.yzcdn.cn/zanui/vant/vant-2017-12-18.ico">
<title>Vant - 有赞移动端 Vue 组件库</title>
<script>window.Promise || document.write('<script src="//b.yzcdn.cn/huiyi/build/h5/js/pinkie.min.js"><\/script>');</script>
</head>
<body ontouchstart>

View File

@ -10,19 +10,21 @@ window.syncPath = function(dir) {
const router = window.vueRouter;
const isInIframe = window !== window.top;
const currentDir = router.history.current.path;
const iframe = document.querySelector('iframe');
const pathParts = currentDir.split('/');
let lang = pathParts[0];
if (currentDir[0] === '/') {
lang = pathParts[1];
}
if (!isInIframe && !isMobile && iframe) {
const pathParts = currentDir.split('/');
let lang = pathParts[0];
if (currentDir[0] === '/') {
lang = pathParts[1];
if (!isInIframe && !isMobile) {
const iframe = document.querySelector('iframe');
if (iframe) {
iframeReady(iframe, () => {
iframe.contentWindow.changePath(lang, currentDir);
});
}
setLang(lang);
iframeReady(iframe, () => {
iframe.contentWindow.changePath(lang, currentDir);
});
} else if (isInIframe) {
window.top.changePath(lang, currentDir);
}
};

View File

@ -12,6 +12,7 @@ const langMap = {
messages: zhCN
}
};
let currentLang = '';
setLang(getDefaultLang());
@ -30,6 +31,11 @@ function getDefaultLang() {
}
export function setLang(lang) {
if (currentLang === lang) {
return;
}
currentLang = lang;
if (window.localStorage) {
localStorage.setItem('VANT_LANGUAGE', lang);
}

2
package-lock.json generated
View File

@ -1,6 +1,6 @@
{
"name": "vant",
"version": "0.12.4",
"version": "0.12.8",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View File

@ -1,6 +1,6 @@
{
"name": "vant",
"version": "0.12.4",
"version": "0.12.8",
"description": "A Vue.js 2.0 Mobile UI at YouZan",
"main": "lib/vant.js",
"style": "lib/vant-css/index.css",
@ -50,7 +50,7 @@
"vue": ">= 2.5.0"
},
"devDependencies": {
"autoprefixer": "^7.2.4",
"autoprefixer": "^7.2.5",
"avoriaz": "2.0.0",
"babel-cli": "^6.26.0",
"babel-core": "^6.26.0",
@ -63,10 +63,10 @@
"chai": "^4.1.2",
"codecov": "^3.0.0",
"cross-env": "^5.1.3",
"css-loader": "^0.28.8",
"dependency-tree": "^5.12.0",
"eslint": "^4.15.0",
"eslint-plugin-vue": "^4.1.0",
"css-loader": "^0.28.9",
"dependency-tree": "^6.0.0",
"eslint": "^4.17.0",
"eslint-plugin-vue": "^4.2.2",
"extract-text-webpack-plugin": "3.0.2",
"fast-vue-md-loader": "^1.0.3",
"friendly-errors-webpack-plugin": "^1.6.1",
@ -82,30 +82,30 @@
"karma-spec-reporter": "^0.0.32",
"karma-webpack": "^2.0.9",
"mocha": "^4.0.1",
"postcss": "^6.0.16",
"postcss": "^6.0.17",
"postcss-calc": "^6.0.0",
"postcss-easy-import": "^3.0.0",
"postcss-loader": "^2.0.10",
"precss": "2.0.0",
"progress-bar-webpack-plugin": "^1.10.0",
"rimraf": "^2.5.4",
"shelljs": "^0.7.8",
"shelljs": "^0.8.1",
"sinon": "^2.4.1",
"sinon-chai": "^2.12.0",
"style-loader": "^0.19.1",
"style-loader": "^0.20.1",
"uppercamelcase": "^3.0.0",
"url-loader": "^0.6.2",
"vant-doc": "1.0.1",
"vant-doc": "1.0.3",
"vue": "^2.5.13",
"vue-loader": "^13.6.2",
"vue-loader": "^14.1.1",
"vue-router": "^3.0.1",
"vue-sfc-compiler": "^0.0.7",
"vue-style-loader": "^3.0.0",
"vue-sfc-compiler": "^0.0.8",
"vue-style-loader": "^3.1.2",
"vue-template-compiler": "^2.5.13",
"vue-template-es2015-compiler": "^1.6.0",
"webpack": "^3.10.0",
"webpack-bundle-analyzer": "^2.9.1",
"webpack-dev-server": "2.9.7",
"webpack-bundle-analyzer": "^2.10.0",
"webpack-dev-server": "2.11.1",
"webpack-merge": "^4.1.1"
}
}

View File

@ -17,7 +17,7 @@
<span class="van-actionsheet__name">{{ item.name }}</span>
<span class="van-actionsheet__subname" v-if="item.subname">{{ item.subname }}</span>
</template>
<loading v-else class="van-actionsheet__loading" type="circle" />
<loading v-else class="van-actionsheet__loading" size="20px" />
</li>
</ul>
<div
@ -60,10 +60,6 @@ export default create({
}
},
mounted() {
this.value && this.open();
},
methods: {
onClickItem(item) {
if (typeof item.callback === 'function') {

View File

@ -44,6 +44,7 @@
:error="errorInfo.postal_code"
@focus="onFocus('postal_code')"
/>
<slot />
<switch-cell
v-if="showSetDefault"
v-show="!hideBottomFields"
@ -158,6 +159,7 @@ export default create({
hideBottomFields() {
return this.searchResult.length && this.detailFocused;
},
computedAddressText() {
return this.addressText || this.$t('addressText');
}

View File

@ -5,7 +5,10 @@
show-toolbar
value-key="name"
:title="title"
:loading="loading"
:columns="columns"
:item-height="itemHeight"
:visible-item-count="visibleItemCount"
@change="onChange"
@confirm="$emit('confirm', $event)"
@cancel="$emit('cancel', $event)"
@ -26,7 +29,10 @@ export default create({
props: {
value: {},
title: String,
loading: Boolean,
areaList: Object,
itemHeight: Number,
visibleItemCount: Number,
// 3-2-1-
columnsNum: {
type: [String, Number],
@ -94,23 +100,23 @@ export default create({
// `code`
getList(type, code) {
if (!this.listValid) {
return [];
}
let result = [];
const { areaList } = this;
const list =
type === 'province'
? areaList.province_list
: type === 'city' ? areaList.city_list : areaList.county_list;
if (this.listValid && (type === 'province' || code)) {
const { areaList } = this;
const list =
type === 'province'
? areaList.province_list
: type === 'city' ? areaList.city_list : areaList.county_list;
let result = Object.keys(list).map(code => ({
code,
name: list[code]
}));
result = Object.keys(list).map(code => ({
code,
name: list[code]
}));
if (type !== 'province' && code) {
result = result.filter(item => item.code.indexOf(code) === 0);
if (type !== 'province' && code) {
result = result.filter(item => item.code.indexOf(code) === 0);
}
}
result.unshift({

View File

@ -16,14 +16,9 @@
]"
@click="onClick"
>
<loading
v-if="loading"
class="van-button__icon-loading"
type="circle"
:color="type === 'default' ? 'black' : 'white'"
/>
<loading v-if="loading" size="20px" :color="type === 'default' ? 'black' : 'white'" />
<span class="van-button__text">
<slot />
<slot>{{ text }}</slot>
</span>
</component>
</template>
@ -35,6 +30,7 @@ export default create({
name: 'van-button',
props: {
text: String,
block: Boolean,
loading: Boolean,
disabled: Boolean,

126
packages/circle/index.vue Normal file
View File

@ -0,0 +1,126 @@
<template>
<div class="van-circle" :style="style">
<svg viewBox="0 0 1060 1060">
<path class="van-circle__hover" :style="hoverStyle" :d="path" />
<path class="van-circle__layer" :style="layerStyle" :d="path" />
</svg>
<slot>
<div class="van-circle__text">{{ text }}</div>
</slot>
</div>
</template>
<script>
import { create } from '../utils';
import { raf, cancel } from '../utils/raf';
export default create({
name: 'van-circle',
props: {
text: String,
value: Number,
speed: Number,
size: {
type: String,
default: '100px'
},
fill: {
type: String,
default: 'none'
},
rate: {
type: Number,
default: 100
},
layerColor: {
type: String,
default: '#fff'
},
color: {
type: String,
default: '#38f'
},
strokeWidth: {
type: Number,
default: 40
},
clockwise: {
type: Boolean,
default: true
}
},
beforeCreate() {
this.perimeter = 3140;
this.path = 'M 530 530 m -500, 0 a 500, 500 0 1, 1 1000, 0 a 500, 500 0 1, 1 -1000, 0';
},
computed: {
style() {
return {
width: this.size,
height: this.size
};
},
layerStyle() {
let offset = this.perimeter * (100 - this.value) / 100;
offset = this.clockwise ? offset : this.perimeter * 2 - offset;
return {
stroke: `${this.color}`,
strokeDashoffset: `${offset}px`,
strokeWidth: `${this.strokeWidth + 1}px`
};
},
hoverStyle() {
return {
fill: `${this.fill}`,
stroke: `${this.layerColor}`,
strokeWidth: `${this.strokeWidth}px`
};
}
},
mounted() {
this.render();
},
watch: {
rate() {
this.render();
}
},
methods: {
render() {
this.startTime = Date.now();
this.startRate = this.value;
this.endRate = this.format(this.rate);
this.increase = this.endRate > this.startRate;
this.duration = Math.abs((this.startRate - this.endRate) * 1000 / this.speed);
if (this.speed) {
cancel(this.rafId);
this.rafId = raf(this.animate);
} else {
this.$emit('input', this.endRate);
}
},
animate() {
const now = Date.now();
const progress = Math.min((now - this.startTime) / this.duration, 1);
const rate = progress * (this.endRate - this.startRate) + this.startRate;
this.$emit('input', this.format(parseFloat(rate.toFixed(1))));
if (this.increase ? rate < this.endRate : rate > this.endRate) {
this.rafId = raf(this.animate);
}
},
format(rate) {
return Math.min(Math.max(rate, 0), 100);
}
}
});
</script>

View File

@ -3,7 +3,7 @@
<cell-group class="van-coupon-list__top" v-if="showExchangeBar">
<field
class="van-coupon-list__filed van-hairline--surround"
v-model="exchangeCode"
v-model="currentCode"
:placeholder="inputPlaceholder || $t('placeholder')"
:maxlength="20"
/>
@ -11,11 +11,11 @@
size="small"
type="danger"
class="van-coupon-list__exchange"
:disabled="exchangeButtonDisabled || !exchangeCode.length"
:text="exchangeButtonText || $t('exchange')"
:loading="exchangeButtonLoading"
:disabled="buttonDisabled"
@click="onClickExchangeButton"
>
{{ exchangeButtonText || $t('exchange') }}
</van-button>
/>
</cell-group>
<div class="van-coupon-list__list" :class="{ 'van-coupon-list--with-exchange': showExchangeBar }" ref="list">
<coupon-item
@ -24,7 +24,7 @@
:key="item.id || item.name"
:data="item"
:chosen="index === chosenCoupon"
@click.native="onClickCoupon(index)"
@click.native="$emit('change', index)"
/>
<h3 v-if="disabledCoupons.length">{{ disabledListTitle || $t('disabled') }}</h3>
<coupon-item
@ -40,11 +40,10 @@
</div>
<div
v-show="showCloseButton"
v-text="closeButtonText || $t('close')"
class="van-coupon-list__close van-hairline--top"
@click="onClickNotUse"
>
{{ closeButtonText || $t('close') }}
</div>
@click="$emit('change', -1)"
/>
</div>
</template>
@ -54,7 +53,6 @@ import Cell from '../cell';
import CellGroup from '../cell-group';
import CouponItem from './Item';
import Field from '../field';
import Popup from '../popup';
import VanButton from '../button';
export default create({
@ -65,15 +63,25 @@ export default create({
Cell,
CellGroup,
Field,
Popup,
CouponItem
},
model: {
prop: 'code'
},
props: {
code: String,
closeButtonText: String,
inputPlaceholder: String,
disabledListTitle: String,
exchangeButtonText: String,
exchangeButtonLoading: Boolean,
exchangeButtonDisabled: Boolean,
exchangeMinLength: {
type: Number,
default: 1
},
chosenCoupon: {
type: Number,
default: -1
@ -86,10 +94,6 @@ export default create({
type: Array,
default: () => []
},
exchangeButtonDisabled: {
type: Boolean,
default: false
},
displayedCouponIndex: {
type: Number,
default: -1
@ -104,16 +108,34 @@ export default create({
}
},
watch: {
displayedCouponIndex(val) {
this.scrollToShowCoupon(val);
data() {
return {
currentCode: this.code || ''
};
},
computed: {
buttonDisabled() {
return (
!this.exchangeButtonLoading &&
(this.exchangeButtonDisabled ||
this.currentCode.length < this.exchangeMinLength)
);
}
},
data() {
return {
exchangeCode: ''
};
watch: {
code(code) {
this.currentCode = code;
},
currentCode(code) {
this.$emit('input', code);
},
displayedCouponIndex(val) {
this.scrollToShowCoupon(val);
}
},
mounted() {
@ -121,17 +143,16 @@ export default create({
},
methods: {
onClickNotUse() {
this.$emit('change', -1);
},
onClickCoupon(index) {
this.$emit('change', index);
},
onClickExchangeButton() {
this.$emit('exchange', this.exchangeCode);
this.exchangeCode = '';
this.$emit('exchange', this.currentCode);
// auto clear currentCode when not use v-model
if (!this.code) {
this.currentCode = '';
}
},
//
// scroll to show specific coupon
scrollToShowCoupon(index) {
if (index === -1) {
return;

View File

@ -50,14 +50,11 @@ export default create({
callback: Function,
confirmButtonText: String,
cancelButtonText: String,
showCancelButton: Boolean,
showConfirmButton: {
type: Boolean,
default: true
},
showCancelButton: {
type: Boolean,
default: false
},
overlay: {
type: Boolean,
default: true

View File

@ -1,31 +1,10 @@
import Vue from 'vue';
import DialogComponent from './dialog';
import VanDialog from './dialog';
let instance;
const defaultOptions = {
value: true,
title: '',
message: '',
overlay: true,
lockOnScroll: true,
confirmButtonText: '',
cancelButtonText: '',
showConfirmButton: true,
showCancelButton: false,
closeOnClickOverlay: false,
callback: action => {
instance[action === 'confirm' ? 'resolve' : 'reject'](action);
}
};
let currentDefaultOptions = {
...defaultOptions
};
const initInstance = () => {
const DialogConstructor = Vue.extend(DialogComponent);
instance = new DialogConstructor({
instance = new (Vue.extend(VanDialog))({
el: document.createElement('div')
});
@ -50,13 +29,29 @@ const Dialog = options => {
});
};
Dialog.defaultOptions = {
value: true,
title: '',
message: '',
overlay: true,
lockOnScroll: true,
confirmButtonText: '',
cancelButtonText: '',
showConfirmButton: true,
showCancelButton: false,
closeOnClickOverlay: false,
callback: action => {
instance[action === 'confirm' ? 'resolve' : 'reject'](action);
}
};
Dialog.alert = options => Dialog({
...currentDefaultOptions,
...Dialog.currentOptions,
...options
});
Dialog.confirm = options => Dialog({
...currentDefaultOptions,
...Dialog.currentOptions,
showCancelButton: true,
...options
});
@ -65,22 +60,19 @@ Dialog.close = () => {
instance.value = false;
};
Dialog.setDefaultOptions = (options = {}) => {
currentDefaultOptions = {
...currentDefaultOptions,
...options
};
Dialog.setDefaultOptions = options => {
Object.assign(Dialog.currentOptions, options);
};
Dialog.resetDefaultOptions = () => {
currentDefaultOptions = {
...defaultOptions
};
Dialog.currentOptions = { ...Dialog.defaultOptions };
};
Dialog.install = () => {
Vue.component(VanDialog.name, VanDialog);
};
Vue.prototype.$dialog = Dialog;
Dialog.resetDefaultOptions();
export default Dialog;
export {
DialogComponent as Dialog
};

View File

@ -12,6 +12,7 @@ import CellGroup from './cell-group';
import CellSwipe from './cell-swipe';
import Checkbox from './checkbox';
import CheckboxGroup from './checkbox-group';
import Circle from './circle';
import Col from './col';
import ContactCard from './contact-card';
import ContactEdit from './contact-edit';
@ -62,7 +63,7 @@ import TreeSelect from './tree-select';
import Uploader from './uploader';
import Waterfall from './waterfall';
const version = '0.12.4';
const version = '0.12.8';
const components = [
Actionsheet,
AddressEdit,
@ -77,6 +78,7 @@ const components = [
CellSwipe,
Checkbox,
CheckboxGroup,
Circle,
Col,
ContactCard,
ContactEdit,
@ -84,6 +86,7 @@ const components = [
CouponCell,
CouponList,
DatetimePicker,
Dialog,
Field,
GoodsAction,
GoodsActionBigBtn,
@ -148,6 +151,7 @@ export {
CellSwipe,
Checkbox,
CheckboxGroup,
Circle,
Col,
ContactCard,
ContactEdit,

View File

@ -1,7 +1,10 @@
<template>
<div class="van-loading" :class="['van-loading--' + type, 'van-loading--' + color]">
<span class="van-loading__spinner" :class="['van-loading__spinner--' + type, 'van-loading__spinner--' + color]">
<i v-if="type === 'spinner'" v-for="item in 12" />
<div class="van-loading" :class="['van-loading--' + type, 'van-loading--' + color]" :style="style">
<span class="van-loading__spinner" :class="'van-loading__spinner--' + type">
<i v-for="item in (type === 'spinner' ? 12 : 0)" />
<svg v-if="type === 'circular'" class="van-loading__circular" viewBox="25 25 50 50">
<circle cx="50" cy="50" r="20" fill="none"/>
</svg>
</span>
</div>
</template>
@ -11,16 +14,28 @@ import install from '../utils/install';
export default {
install,
name: 'van-loading',
props: {
size: String,
type: {
type: String,
default: 'gradient-circle'
default: 'circular'
},
color: {
type: String,
default: 'black'
}
},
computed: {
style() {
return this.size ? {
width: this.size,
height: this.size
} : {};
}
}
};
</script>

View File

@ -113,10 +113,12 @@ export default {
},
vanSkuMessages: {
fill: 'Please fill',
upload: 'Please upload',
number: 'Please fill in the correct number format message',
email: 'Please fill in the correct email message',
idcard: 'Please fill in the correct ID number message',
overlimit: 'not more than 200 words',
onePic: 'only one picture',
placeholder: {
'id_no': 'Idcard Number',
text: 'Text',
@ -127,6 +129,15 @@ export default {
textarea: 'Text'
}
},
vanSkuImgUploader: {
or: 'Or',
uploading: 'Uploading...',
rephoto: 'Take Again',
photo: 'Take',
reselect: 'Reselect',
select: 'Select Photo',
maxSize: maxSize => `The upload limit is up to ${maxSize}MBplease try to compress the photo`
},
vanSkuStepper: {
title: 'Quantity',
remain: count => `Remain ${count} items`,

View File

@ -117,10 +117,12 @@ export default {
},
vanSkuMessages: {
fill: '请填写',
upload: '请上传',
number: '请填写正确的数字格式留言',
email: '请填写正确的邮箱',
'id_no': '请填写正确的身份证号码',
overlimit: '写的太多了不要超过200字',
onePic: '仅限一张',
placeholder: {
'id_no': '输入18位身份证号码',
text: '输入文本',
@ -131,6 +133,15 @@ export default {
textarea: '点击填写段落文本'
}
},
vanSkuImgUploader: {
or: '或',
uploading: '正在上传...',
rephoto: '重拍',
photo: '拍照',
reselect: '重新选择照片',
select: '选择照片',
maxSize: maxSize => `最大可上传图片为${maxSize}MB请尝试压缩图片尺寸`
},
vanSkuStepper: {
title: '购买数量',
remain: count => `剩余${count}`,

View File

@ -19,6 +19,8 @@ export default {
zIndex: [String, Number],
// prevent touchmove scroll
preventScroll: Boolean,
// return the mount node for popup
getContainer: Function,
// prevent body scroll
lockOnScroll: {
type: Boolean,
@ -26,17 +28,8 @@ export default {
}
},
watch: {
value(val) {
this[val ? 'open' : 'close']();
}
},
beforeMount() {
this._popupId = 'popup-' + context.plusKey('idSeed');
},
data() {
this._popupId = 'popup-' + context.plusKey('idSeed');
return {
opened: false,
pos: {
@ -46,6 +39,29 @@ export default {
};
},
watch: {
value(val) {
this[val ? 'open' : 'close']();
},
getContainer() {
this.move();
}
},
mounted() {
if (this.getContainer) {
this.move();
}
if (this.value) {
this.open();
}
},
beforeDestroy() {
this.doAfterClose();
},
methods: {
recordPosition(e) {
this.pos = {
@ -65,12 +81,14 @@ export default {
let status = '11';
/* istanbul ignore next */
if (scrollTop === 0) {
status = offsetHeight >= scrollHeight ? '00' : '01';
} else if (scrollTop + offsetHeight >= scrollHeight) {
status = '10';
}
/* istanbul ignore next */
if (
status !== '11' &&
isVertical &&
@ -82,6 +100,7 @@ export default {
},
open() {
/* istanbul ignore next */
if (this.opened || this.$isServer) {
return;
}
@ -137,10 +156,14 @@ export default {
off(document, 'touchstart', this.recordPosition);
off(document, 'touchmove', this.watchTouchMove);
}
}
},
},
beforeDestroy() {
this.doAfterClose();
move() {
if (this.getContainer) {
this.getContainer().appendChild(this.$el);
} else if (this.$parent) {
this.$parent.$el.appendChild(this.$el);
}
}
}
};

Some files were not shown because too many files have changed in this diff Show More