Merge branch 'dev'

This commit is contained in:
niunai 2018-03-22 16:09:58 +08:00
commit a1fef47e9b
215 changed files with 9136 additions and 5464 deletions

26
LICENSE
View File

@ -1,29 +1,7 @@
Copyright 2017-present Youzan
Copyright 2016-present Youzan
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
The MIT License (MIT)
Copyright (c) 2016 ElemeFE
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -6,7 +6,7 @@
<img alt="logo" src="https://img.yzcdn.cn/public_files/2017/12/18/fd78cf6bb5d12e2a119d0576bedfd230.png" width="120" height="120" style="margin-bottom: 10px;">
</p>
<p align="center">A Vue.js 2.0 Mobile UI at YouZan</p>
<p align="center" style="margin: 30px 0 35px;">A Vue.js 2.0 Mobile UI at YouZan</p>
[![Build Status](https://travis-ci.org/youzan/vant.svg?branch=master)](https://travis-ci.org/youzan/vant)
[![downloads](https://img.shields.io/npm/dt/vant.svg)](https://www.npmjs.com/package/vant)
@ -18,17 +18,13 @@
## Features
* 48+ Reusable components
* 50+ Reusable components
* 90%+ Unit test coverage
* Extensive documentation and demos
* Support [babel-plugin-import](https://github.com/ant-design/babel-plugin-import)
* Support TypeScript
* Support SSR
<p align="center">
<img alt="components preview" src="https://img.yzcdn.cn/public_files/2017/12/05/95f5ee7524b7845abb2f51803a01d65e.png">
</p >
## Install
```shell
@ -100,7 +96,7 @@ Modern browsers and Android 4.0+, iOS 6+.
## Links
* [Documentation](https://www.youzanyun.com/zanui/vant)
* [Changelog](https://www.youzanyun.com/zanui/vant#/en-US/component/changelog)
* [Changelog](https://www.youzanyun.com/zanui/vant#/en-US/changelog)
* [React UI](https://www.youzanyun.com/zanui/zent)
* [Weapp UI](https://github.com/youzan/zanui-weapp)
* [Vant Demo](https://github.com/youzan/vant-demo)

View File

@ -5,7 +5,7 @@
<p align="center">
<img alt="logo" src="https://img.yzcdn.cn/public_files/2017/12/18/fd78cf6bb5d12e2a119d0576bedfd230.png" width="120" style="margin-bottom: 10px;">
</p>
<p align="center">A Vue.js 2.0 Mobile UI at YouZan</p>
<p align="center" style="margin: 30px 0 35px;">A Vue.js 2.0 Mobile UI at YouZan</p>
[![Build Status](https://travis-ci.org/youzan/vant.svg?branch=master)](https://travis-ci.org/youzan/vant)
[![downloads](https://img.shields.io/npm/dt/vant.svg)](https://www.npmjs.com/package/vant)
@ -15,16 +15,12 @@
## 特性
* 48+ 个经过有赞线上业务检验的组件
* 50+ 个经过有赞线上业务检验的组件
* 单元测试覆盖率超过 90%
* 完善的文档和示例
* 完善的中英文文档和示例
* 支持 [babel-plugin-import](https://github.com/ant-design/babel-plugin-import)
* 支持 TypeScript
* 支持 SSR
<p align="center">
<img alt="components preview" src="https://img.yzcdn.cn/public_files/2017/12/05/95f5ee7524b7845abb2f51803a01d65e.png">
</p >
## 安装
@ -84,7 +80,7 @@ Vue.use(Vant);
<script src="https://unpkg.com/vant/lib/vant.min.js"></script>
```
更多内容请参考 [快速上手](https://www.youzanyun.com/zanui/vant#/zh-CN/component/quickstart).
更多内容请参考 [快速上手](https://www.youzanyun.com/zanui/vant#/zh-CN/quickstart).
## 贡献代码
@ -105,7 +101,7 @@ Vue.use(Vant);
## 链接
* [详细文档](https://www.youzanyun.com/zanui/vant)
* [更新日志](https://www.youzanyun.com/zanui/vant#/zh-CN/component/changelog)
* [更新日志](https://www.youzanyun.com/zanui/vant#/zh-CN/changelog)
* [React 组件库](https://www.youzanyun.com/zanui/zent)
* [微信小程序组件库](https://github.com/youzan/zanui-weapp)
* [vant-demo](https://github.com/youzan/vant-demo)

View File

@ -8,10 +8,7 @@ const tips = '// This file is auto gererated by build/bin/build-entry.js';
function buildVantEntry() {
const uninstallComponents = [
'Lazyload',
'Waterfall',
'Toast',
'ImagePreview',
'Locale'
'Waterfall'
];
const importList = Components.map(name => `import ${uppercamelize(name)} from './${name}';`);

View File

@ -17,19 +17,20 @@ components.forEach(componentName => {
// Analyze component dependencies
function analyzeDependencies(componentName, libDir) {
const checkList = ['base'];
const whiteList = ['icon', 'loading', 'cell', 'button'];
search(dependencyTree({
directory: libDir,
filename: path.resolve(libDir, componentName, 'index.js'),
filter: path => path.indexOf(`vant${SEP}lib${SEP}`) !== -1
}), checkList);
}), checkList, whiteList);
return checkList.filter(component => checkComponentHasStyle(component));
}
function search(tree, checkList) {
function search(tree, checkList, whiteList) {
tree && Object.keys(tree).forEach(key => {
search(tree[key], checkList);
search(tree[key], checkList, whiteList);
const component = key.split(`${SEP}vant${SEP}lib${SEP}`)[1].replace(`${SEP}index.js`, '').replace(`mixins${SEP}`, '');
if (checkList.indexOf(component) === -1) {
if (checkList.indexOf(component) === -1 && whiteList.indexOf(component) === -1) {
checkList.push(component);
}
});

View File

@ -1,16 +1,20 @@
const path = require('path');
const webpack = require('webpack');
const config = require('./webpack.config.dev.js');
const isMinify = process.argv.indexOf('-p') !== -1;
module.exports = Object.assign({}, config, {
mode: 'production',
entry: {
'vant': './packages/index.js'
},
output: {
filename: isMinify ? './lib/[name].min.js' : './lib/[name].js',
path: path.join(__dirname, '../lib'),
library: 'vant',
libraryTarget: 'umd',
umdNamedDefine: true
filename: isMinify ? '[name].min.js' : '[name].js',
umdNamedDefine: true,
globalObject: 'this'
},
externals: {
vue: {
@ -20,10 +24,9 @@ module.exports = Object.assign({}, config, {
amd: 'vue'
}
},
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV': '"production"'
}),
new webpack.optimize.ModuleConcatenationPlugin()
]
plugins: [],
performance: false,
optimization: {
minimize: isMinify
}
});

View File

@ -3,16 +3,10 @@ const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const ProgressBarPlugin = require('progress-bar-webpack-plugin');
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin');
const isProduction = process.env.NODE_ENV === 'production';
const cache = {
loader: 'cache-loader',
options: {
cacheDirectory: path.resolve(__dirname, '../node_modules/.cache-loader')
}
};
module.exports = {
mode: 'development',
entry: {
'vant-docs': './docs/src/index.js',
'vant-mobile': './docs/src/mobile.js'
@ -20,7 +14,6 @@ module.exports = {
output: {
path: path.join(__dirname, '../docs/dist'),
publicPath: '/',
filename: '[name].js',
chunkFilename: 'async_[name].js'
},
devServer: {
@ -34,21 +27,17 @@ module.exports = {
stats: 'errors-only'
},
resolve: {
modules: [path.join(__dirname, '../node_modules'), 'node_modules'],
extensions: ['.js', '.vue', '.css'],
alias: {
vue: 'vue/dist/vue.runtime.esm.js',
packages: path.join(__dirname, '../packages'),
lib: path.join(__dirname, '../lib'),
components: path.join(__dirname, '../docs/src/components')
packages: path.join(__dirname, '../packages')
}
},
module: {
loaders: [
rules: [
{
test: /\.vue$/,
use: [
cache,
{
loader: 'vue-loader',
options: {
@ -61,10 +50,7 @@ module.exports = {
{
test: /\.js$/,
exclude: /node_modules|vue-router\/|vue-loader\//,
use: [
cache,
'babel-loader'
]
use: 'babel-loader'
},
{
test: /\.css$/,
@ -78,7 +64,6 @@ module.exports = {
{
test: /\.md/,
use: [
cache,
'vue-loader',
'fast-vue-md-loader'
]
@ -103,15 +88,9 @@ module.exports = {
filename: 'examples.html',
inject: true
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: 2,
filename: isProduction ? 'vendor.[hash:8].js' : 'vendor.js'
}),
new ExtractTextPlugin({
filename: isProduction ? '[name].[hash:8].css' : '[name].css',
allChunks: true
}),
new FriendlyErrorsPlugin()
})
]
};

View File

@ -4,19 +4,12 @@ const path = require('path');
const devConfig = require('./webpack.config.dev.js');
module.exports = merge(devConfig, {
mode: 'production',
output: {
path: path.join(__dirname, '../docs/dist'),
publicPath: 'https://img.yzcdn.cn/zanui/vant/',
filename: '[name].[hash:8].js',
umdNamedDefine: true,
chunkFilename: 'async_[name].[chunkhash:8].js'
},
plugins: [
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify(process.env.NODE_ENV)
}
}),
new webpack.optimize.UglifyJsPlugin()
]
}
});

View File

@ -33,6 +33,7 @@ export default {
'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')),
'collapse': asyncWrapper(r => require.ensure([], () => r(componentWrapper(require('./views/collapse'), 'collapse')), 'collapse')),
'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')),
@ -43,6 +44,7 @@ export default {
'image-preview': asyncWrapper(r => require.ensure([], () => r(componentWrapper(require('./views/image-preview'), 'image-preview')), 'image-preview')),
'layout': asyncWrapper(r => require.ensure([], () => r(componentWrapper(require('./views/layout'), 'layout')), 'layout')),
'lazyload': asyncWrapper(r => require.ensure([], () => r(componentWrapper(require('./views/lazyload'), 'lazyload')), 'lazyload')),
'list': asyncWrapper(r => require.ensure([], () => r(componentWrapper(require('./views/list'), 'list')), 'list')),
'loading': asyncWrapper(r => require.ensure([], () => r(componentWrapper(require('./views/loading'), 'loading')), 'loading')),
'nav-bar': asyncWrapper(r => require.ensure([], () => r(componentWrapper(require('./views/nav-bar'), 'nav-bar')), 'nav-bar')),
'notice-bar': asyncWrapper(r => require.ensure([], () => r(componentWrapper(require('./views/notice-bar'), 'notice-bar')), 'notice-bar')),

3607
docs/demos/mock/area.js Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

71
docs/demos/mock/areaEn.js Normal file
View File

@ -0,0 +1,71 @@
export default {
'province_list': {
'110000': 'Beijing',
'330000': 'Zhejiang',
'810000': 'Hong Kong'
},
'city_list': {
'110100': 'Beijing City',
'330100': 'Hangzhou',
'330200': 'Ningbo',
'330300': 'Wenzhou',
'330400': 'Jiaxin',
'331100': 'Lishui',
'810100': 'Hong Kong Island',
'810200': 'Kowloon',
'810300': 'New Territories'
},
'county_list': {
'110101': 'Dongcheng',
'110102': 'Xicheng',
'110105': 'Chaoyang',
'110106': 'Fengtai',
'110108': 'Haidian',
'110111': 'Fangshan',
'110112': 'Tongzhou',
'110113': 'Shunyi',
'110114': 'Changping',
'110115': 'Daxing',
'330105': 'Gongshu',
'330106': 'Xihu',
'330108': 'Binjiang',
'330109': 'Xiaoshan',
'330110': 'Yuhang',
'330111': 'Fuyang',
'330127': 'Chunan',
'330182': 'Jiande',
'330185': 'Linan',
'330206': 'Beilun',
'330211': 'Zhenhai',
'330225': 'Xiangshan',
'330226': 'Ninghai',
'330281': 'Yuyao',
'330282': 'Cixi',
'330327': 'Cangnan',
'330328': 'Wencheng',
'330329': 'Shuntai',
'330381': 'Ruian',
'330382': 'Yueqing',
'330402': 'Nanhu',
'330421': 'Jiashan',
'330424': 'Haiyan',
'330481': 'Haining',
'330482': 'Pinghu',
'330483': 'Tongxiang',
'331102': 'Liandu District',
'331121': 'Qingtian County',
'331125': 'Yunhe County',
'331181': 'Longquan County',
'810101': 'Central',
'810102': 'Wan Chai',
'810202': 'Mong Kok',
'810203': 'Sham Shui Po',
'810204': 'Chuk Un',
'810205': 'Kwun Tong',
'810303': 'Sha Tin',
'810305': 'Yuen Long',
'810306': 'Tuen Mun',
'810307': 'Tsuen Wan',
'810309': 'Lantau Island'
}
}

View File

@ -1,71 +0,0 @@
{
"province_list": {
"110000": "Beijing",
"330000": "Zhejiang",
"810000": "Hong Kong"
},
"city_list": {
"110100": "Beijing City",
"330100": "Hangzhou",
"330200": "Ningbo",
"330300": "Wenzhou",
"330400": "Jiaxin",
"331100": "Lishui",
"810100": "Hong Kong Island",
"810200": "Kowloon",
"810300": "New Territories"
},
"county_list": {
"110101": "Dongcheng",
"110102": "Xicheng",
"110105": "Chaoyang",
"110106": "Fengtai",
"110108": "Haidian",
"110111": "Fangshan",
"110112": "Tongzhou",
"110113": "Shunyi",
"110114": "Changping",
"110115": "Daxing",
"330105": "Gongshu",
"330106": "Xihu",
"330108": "Binjiang",
"330109": "Xiaoshan",
"330110": "Yuhang",
"330111": "Fuyang",
"330127": "Chunan",
"330182": "Jiande",
"330185": "Linan",
"330206": "Beilun",
"330211": "Zhenhai",
"330225": "Xiangshan",
"330226": "Ninghai",
"330281": "Yuyao",
"330282": "Cixi",
"330327": "Cangnan",
"330328": "Wencheng",
"330329": "Shuntai",
"330381": "Ruian",
"330382": "Yueqing",
"330402": "Nanhu",
"330421": "Jiashan",
"330424": "Haiyan",
"330481": "Haining",
"330482": "Pinghu",
"330483": "Tongxiang",
"331102": "Liandu District",
"331121": "Qingtian County",
"331125": "Yunhe County",
"331181": "Longquan County",
"810101": "Central",
"810102": "Wan Chai",
"810202": "Mong Kok",
"810203": "Sham Shui Po",
"810204": "Chuk Un",
"810205": "Kwun Tong",
"810303": "Sha Tin",
"810305": "Yuen Long",
"810306": "Tuen Mun",
"810307": "Tsuen Wan",
"810309": "Lantau Island"
}
}

View File

@ -27,14 +27,16 @@ export default {
button2: '弹出带取消按钮的 Actionsheet',
button3: '弹出带标题的 Actionsheet',
title2: '带取消按钮的 Actionsheet',
title3: '带标题的 Actionsheet'
title3: '带标题的 Actionsheet',
description: '描述信息'
},
'en-US': {
button1: 'Show Actionsheet',
button2: 'Show Actionsheet with cancel button',
button3: 'Show Actionsheet with title',
title2: 'Actionsheet with cancel button',
title3: 'Actionsheet with title'
title3: 'Actionsheet with title',
description: 'Description'
}
},
@ -50,7 +52,7 @@ export default {
actions() {
return [
{ name: this.$t('option'), callback: this.onClick },
{ name: this.$t('option') },
{ name: this.$t('option'), subname: this.$t('description') },
{ name: this.$t('option'), loading: true }
];
}

View File

@ -4,6 +4,7 @@
<van-address-edit
:area-list="areaList"
show-postal
show-delete
show-set-default
show-search-result
:search-result="searchResult"
@ -16,7 +17,7 @@
</template>
<script>
import areaList from '../mock/area.json';
import areaList from '../mock/area';
export default {
i18n: {
@ -25,7 +26,7 @@ export default {
name: '黄龙万科中心',
address: '杭州市西湖区'
}, {
name: '黄龙万科中心H座'
name: '黄龙万科中心G座'
}, {
name: '黄龙万科中心H座',
address: '杭州市西湖区'
@ -33,12 +34,12 @@ export default {
},
'en-US': {
searchResult: [{
name: 'Name',
name: 'Name1',
address: 'Address'
}, {
name: 'Name'
name: 'Name2'
}, {
name: 'Name',
name: 'Name3',
address: 'Address'
}]
}

View File

@ -15,8 +15,8 @@
</template>
<script>
import AreaList from '../mock/area.json';
import AreaListEn from '../mock/areaEn.json';
import AreaList from '../mock/area';
import AreaListEn from '../mock/areaEn';
export default {
i18n: {

View File

@ -71,21 +71,18 @@ export default {
.demo-cell-swipe {
user-select: none;
.van-cell-swipe__left,
.van-cell-swipe__right {
.van-cell-swipe {
&__left,
&__right {
color: #FFFFFF;
font-size: 16px;
font-size: 15px;
width: 65px;
height: 44px;
display: inline-block;
text-align: center;
line-height: 44px;
}
.van-cell-swipe__left {
background-color: #FF4444;
}
.van-cell-swipe__right {
background-color: #84c483;
background-color: #F44;
}
}
}
</style>

View File

@ -0,0 +1,83 @@
<template>
<demo-section>
<demo-block :title="$t('basicUsage')">
<van-collapse v-model="active1">
<van-collapse-item :title="$t('title1')">{{ $t('content1') }}</van-collapse-item>
<van-collapse-item :title="$t('title2')">{{ $t('content2') }}</van-collapse-item>
<van-collapse-item :title="$t('title3')">{{ $t('content3') }}</van-collapse-item>
</van-collapse>
</demo-block>
<demo-block :title="$t('accordion')">
<van-collapse v-model="active2" accordion>
<van-collapse-item :title="$t('title1')">{{ $t('content1') }}</van-collapse-item>
<van-collapse-item :title="$t('title2')">{{ $t('content2') }}</van-collapse-item>
<van-collapse-item :title="$t('title3')">{{ $t('content3') }}</van-collapse-item>
</van-collapse>
</demo-block>
<demo-block :title="$t('titleSlot')">
<van-collapse v-model="active3">
<van-collapse-item>
<div slot="title">{{ $t('title1') }}<van-icon name="question" /></div>
{{ $t('content1') }}
</van-collapse-item>
<van-collapse-item :title="$t('title2')">{{ $t('content2') }}</van-collapse-item>
</van-collapse>
</demo-block>
</demo-section>
</template>
<script>
export default {
i18n: {
'zh-CN': {
accordion: '手风琴',
titleSlot: '自定义标题内容',
title1: '有赞微商城',
title2: '有赞零售',
title3: '有赞美业',
content1: '提供多样店铺模板,快速搭建网上商城',
content2: '网店吸粉获客、会员分层营销、一机多种收款,告别经营低效和客户流失',
content3: '线上拓客,随时预约,贴心顺手的开单收银'
},
'en-US': {
accordion: 'Accordion',
titleSlot: 'Custom title',
title1: 'Title1',
title2: 'Title2',
title3: 'Title3',
content1: 'Only those who have the patience to do simple things perfectly ever acquire the skill to do difficult things easily.',
content2: 'When someone walk out your life, let them. They are just making more room for someone else better to walk in.',
content3: 'The world is big and life is short. Live the life the way you want.'
}
},
data() {
return {
active1: [0],
active2: 0,
active3: []
};
}
};
</script>
<style lang="postcss">
@import "../../../packages/vant-css/src/common/var.css";
.demo-collapse {
.van-collapse-item__content {
font-size: 13px;
line-height: 1.5;
color: $gray-darker;
}
.van-icon-question {
color: $blue;
vertical-align: -3px;
margin-left: 5px;
font-size: 15px;
}
}
</style>

View File

@ -1,6 +1,6 @@
<template>
<demo-section>
<demo-block :title="$t('basicUsage')">
<demo-block :title="$t('title1')">
<van-datetime-picker
v-model="currentDate1"
type="datetime"
@ -15,8 +15,6 @@
<van-datetime-picker
v-model="currentDate2"
type="date"
:min-hour="minHour"
:max-hour="maxHour"
:min-date="minDate"
/>
</demo-block>
@ -24,8 +22,15 @@
<demo-block :title="$t('title3')">
<van-datetime-picker
v-model="currentDate3"
type="year-month"
:min-date="minDate"
/>
</demo-block>
<demo-block :title="$t('title4')">
<van-datetime-picker
v-model="currentDate4"
type="time"
:visibleItemCount="3"
:min-hour="minHour"
:max-hour="maxHour"
:min-date="minDate"
@ -38,12 +43,16 @@
export default {
i18n: {
'zh-CN': {
title2: '选择日期',
title3: '选择时间'
title1: '选择完整时间',
title2: '选择日期(年月日)',
title3: '选择日期(年月)',
title4: '选择时间'
},
'en-US': {
title2: 'Date Picker',
title3: 'Time Picker'
title1: 'Choose DateTime',
title2: 'Choose Date',
title3: 'Choose Year-Month',
title4: 'Choose Time'
}
},
@ -55,7 +64,8 @@ export default {
maxDate: new Date(2019, 10, 1),
currentDate1: new Date(2018, 0, 1),
currentDate2: null,
currentDate3: '12:00'
currentDate3: new Date(2018, 0, 1),
currentDate4: '12:00'
};
}
};

View File

@ -53,7 +53,7 @@
type="textarea"
:placeholder="$t('messagePlaceholder')"
rows="1"
autosize
:autosize="{ maxHeight: 100, minHeight: 40 }"
/>
</van-cell-group>
</demo-block>

79
docs/demos/views/list.vue Normal file
View File

@ -0,0 +1,79 @@
<template>
<demo-section>
<demo-block :title="$t('basicUsage')">
<p class="page-desc">{{ $t('text') }}</p>
<van-pull-refresh v-model="refreshing" @refresh="onRefresh">
<van-list
v-model="loading"
:finished="finished"
@load="onLoad"
>
<van-cell v-for="item in list" :key="item" :title="item + ''" />
</van-list>
</van-pull-refresh>
</demo-block>
</demo-section>
</template>
<script>
export default {
i18n: {
'zh-CN': {
text: '当即将滚动到元素底部时,会自动加载更多'
},
'en-US': {
text: 'This list will load items will scroll to bottom.'
}
},
data() {
return {
list: [],
refreshing: false,
loading: false,
finished: false
};
},
methods: {
onLoad() {
setTimeout(() => {
for (let i = 0; i < 10; i++) {
const text = this.list.length + 1;
this.list.push(text < 10 ? '0' + text : text);
}
this.loading = false;
if (this.list.length >= 40) {
this.finished = true;
}
}, 500);
},
onRefresh() {
setTimeout(() => {
this.list = [];
this.finished = false;
this.refreshing = false;
window.scrollTo(0, 10);
}, 1000);
}
}
};
</script>
<style lang="postcss">
.demo-list {
.van-cell {
text-align: center;
}
.page-desc {
padding: 5px 0;
line-height: 1.4;
font-size: 14px;
text-align: center;
color: #666;
}
}
</style>

View File

@ -2,21 +2,19 @@
<demo-section>
<demo-block :title="$t('basicUsage')">
<van-button @click="show1 = true">{{ $t('button1') }}</van-button>
<van-popup v-model="show1" prevent-scroll>{{ $t('content') }}</van-popup>
<van-popup v-model="show1">{{ $t('content') }}</van-popup>
</demo-block>
<demo-block :title="$t('position')">
<van-button @click="show2 = true;">{{ $t('button2') }}</van-button>
<van-popup v-model="show2" position="bottom" prevent-scroll>
<van-popup v-model="show2" position="bottom">
<van-tabs>
<van-tab class="custom-pane" title="Tab1">
<ul class="scroller">
<li v-for="i in 30" :key="i" class="list-item">{{ i }} item item item</li>
</ul>
<van-tab title="Tab1">
<van-cell v-for="i in 20" :key="i" :title="`Item ${ i }`" />
</van-tab>
<van-tab class="custom-pane" title="Tab2">
<p class="long-text">Lorem ipsum dolor sit amet, quis interdum et sollicitudin consectetuer scelerisque, gravida nulla consequatur dis mauris non morbi, dictum leo enim elementum ac wisi nullam, nam orci erat. Ultrices est. Nunc penatibus vel varius odio. Ullamcorper placerat amet amet sed, urna tempor, elit elit at. Eget congue. Sed proin metus sapien libero, pulvinar ut, ut aenean fermentum magna placerat dapibus voluptas, sed at lacinia pede fermentum rutrum et. Vitae nulla sapien vel in hac felis, montes in donec nulla eu volutpat augue.</p>
<van-tab title="Tab2">
Lorem ipsum dolor sit amet, quis interdum et sollicitudin consectetuer scelerisque, gravida nulla consequatur dis mauris non morbi, dictum leo enim elementum ac wisi nullam, nam orci erat. Ultrices est. Nunc penatibus vel varius odio. Ullamcorper placerat amet amet sed, urna tempor, elit elit at. Eget congue. Sed proin metus sapien libero, pulvinar ut, ut aenean fermentum magna placerat dapibus voluptas, sed at lacinia pede fermentum rutrum et. Vitae nulla sapien vel in hac felis, montes in donec nulla eu volutpat augue.
</van-tab>
</van-tabs>
</van-popup>
@ -107,20 +105,15 @@ export default {
}
.van-tabs__content {
height: 166px;
height: 156px;
overflow-y: scroll;
-webkit-overflow-scrolling: touch;
.list-item {
padding: 10px 10px;
&:not(:last-child) {
border-bottom: 1px solid #f9f9f9;
}
}
.long-text {
padding: 10px;
line-height: 1.4;
color: #666;
}
}
.van-tab__pane:not(:first-child) {
padding: 10px;
line-height: 1.4;
color: #666;
}
&--top {

View File

@ -45,7 +45,7 @@ export default {
.van-pull-refresh {
&,
&__track {
height: 100%;
height: calc(100vh - 50px);
}
}

View File

@ -33,6 +33,7 @@
:quota="$t('sku').quota"
:quota-used="$t('sku').quota_used"
:custom-stepper-config="customStepperConfig"
:message-config="messageConfig"
@buy-clicked="onBuyClicked"
@add-cart="onAddCartClicked"
/>
@ -54,9 +55,15 @@
show-add-cart-btn
reset-stepper-on-hide
:initial-sku="initialSku"
:message-config="messageConfig"
@buy-clicked="onBuyClicked"
@add-cart="onAddCartClicked"
>
<template slot="sku-header-price" slot-scope="props">
<div class="van-sku__goods-price">
<span class="van-sku__price-symbol"></span><span class="van-sku__price-num">{{ props.price }}</span> only!!!
</div>
</template>
<template slot="sku-actions" slot-scope="props">
<div class="van-sku-actions">
<van-button bottom-action @click="onPointClicked">{{ $t('button1') }}</van-button>
@ -119,9 +126,9 @@ export default {
}
},
messageConfig: {
uploadImg: () => {
return new Promise((resolve) => {
setTimeout(() => resolve('https://img.yzcdn.cn/upload_files/2017/02/21/FjKTOxjVgnUuPmHJRdunvYky9OHP.jpg!100x100.jpg'), 1000);
uploadImg: (file, img) => {
return new Promise(resolve => {
setTimeout(() => resolve(img), 1000);
});
},
uploadMaxSize: 3

View File

@ -54,7 +54,7 @@ export default {
step2: '商家接单',
step3: '买家提货',
step4: '交易完成',
title2: '物流描述',
title2: '描述信息',
title3: '竖向步骤条',
status1: '【城市】物流状态1',
status2: '【城市】物流状态',

View File

@ -13,7 +13,7 @@
</demo-block>
<demo-block :title="$t('advancedUsage')">
<van-switch :value="checked2" @input="onInput" />
<van-switch :value="checked2" size="36px" @input="onInput" />
</demo-block>
</demo-section>
</template>

View File

@ -58,6 +58,14 @@
</van-tab>
</van-tabs>
</demo-block>
<demo-block :title="$t('title8')">
<van-tabs :active="active" swipeable>
<van-tab :title="$t('tab') + index" v-for="index in tabs" :key="index">
{{ $t('content') }} {{ index }}
</van-tab>
</van-tabs>
</demo-block>
</demo-section>
</template>
@ -71,7 +79,8 @@ export default {
title4: '样式风格',
title5: '点击事件',
title6: '粘性布局',
title7: '自定义标签'
title7: '自定义标签',
title8: '滑动切换'
},
'en-US': {
tab: 'Tab ',
@ -81,7 +90,8 @@ export default {
title4: 'Card Style',
title5: 'Click Event',
title6: 'Sticky',
title7: 'Custom Tab'
title7: 'Custom Tab',
title8: 'Swipeable'
}
},
@ -106,7 +116,7 @@ export default {
<style lang="postcss">
.demo-tab {
margin-bottom: 500px;
margin-bottom: 300px;
.van-tab .van-icon {
margin-right: 5px;

View File

@ -1,5 +1,6 @@
<template>
<demo-section>
<van-notice-bar>{{ $t('tips') }}</van-notice-bar>
<demo-block :title="$t('basicUsage')">
<p class="page-desc">{{ $t('text') }}</p>
<ul
@ -18,10 +19,12 @@ import { Waterfall } from 'packages';
export default {
i18n: {
'zh-CN': {
text: '当即将滚动到元素底部时,会自动加载更多'
text: '当即将滚动到元素底部时,会自动加载更多',
tips: '注意Waterfall 已被废弃,请使用 List 组件代替'
},
'en-US': {
text: 'This list will load items will scroll to bottom.'
text: 'This list will load items will scroll to bottom.',
tips: 'Waterfall is deprecated and no longer maintained, please use the List component instead.'
}
},

View File

@ -22,9 +22,18 @@ export default {
return {
show: false,
actions: [
{ name: 'Option1', callback: this.onClick },
{ name: 'Option2' },
{ name: 'Option3', loading: true }
{
name: 'Option',
callback: this.onClick
},
{
name: 'Option',
description: 'Description'
},
{
name: 'Option',
loading: true
}
]
};
},

View File

@ -16,6 +16,7 @@ Vue.use(AddressEdit);
<van-address-edit
:area-list="areaList"
show-postal
show-delete
show-set-default
show-search-result
:search-result="searchResult"
@ -64,6 +65,7 @@ export default {
| address-info | Address Info | `Object` | `{}` | - |
| search-result | Address search result | `Array` | `[]` | - |
| show-postal | Whether to show postal field | `Boolean` | `false` | - |
| show-delete | Whether to show delete button | `Boolean` | `false` | - |
| show-set-default | Whether to show default address switch | `Boolean` | `false` | - |
| show-search-result | Whether to show address search result | `Boolean` | `false` | - |
| is-saving | Whether to show save button loading status | `Boolean` | `false` | - |
@ -98,7 +100,7 @@ export default {
| address_detail | Detailed Address | `String` |
| area_code | Area code | `String` |
| postal_code | Postal code | `String` |
| is_default | Is default address | `String` |
| is_default | Is default address | `Boolean` |
#### searchResult Data Structure
| key | Description | Type |

View File

@ -86,7 +86,7 @@ Example of `AreaList`
}
```
All code of China: [Area.json](https://github.com/youzan/vant/blob/dev/docs/demos/mock/area.json)
All code of China: [Area.json](https://github.com/youzan/vant/blob/dev/docs/demos/mock/area.js)
#### argument of callback function confirm
An array contains selected area objects.

View File

@ -76,3 +76,9 @@ Use `tag` prop to custom button tag
| loading | Whether show loading status | `Boolean` | `false` | - |
| block | Whether to set display block | `Boolean` | `false` | - |
| bottom-action | Whether to be action button | `Boolean` | `false` | - |
### Event
| Event | Description | Arguments |
|-----------|-----------|-----------|
| click | Triggered when click button and not disabled or loading | - |

View File

@ -82,7 +82,13 @@ Vue.use(Cell).use(CellGroup);
| is-link | Whether to show link icon | `Boolean` | `false` | - |
| required | Whether to show required mark | `Boolean` | `false` | - |
### Slot
### Cell Event
| Event | Description | Arguments |
|-----------|-----------|-----------|
| click | Triggered when click cell | - |
### Cell Slot
| name | Description |
|-----------|-----------|

View File

@ -1,5 +1,66 @@
## Changelog
### [1.0.1](https://github.com/youzan/vant/tree/v1.0.1)
`2018-03-19`
**Bug Fixes**
- fix module circular dependency [\#728](https://github.com/youzan/vant/pull/728) [@chenjiahan](https://github.com/chenjiahan)
### [1.0.0](https://github.com/youzan/vant/tree/v1.0.0)
`2018-03-19`
**Breaking changes**
* add List component [\#682](https://github.com/youzan/vant/pull/682) [@chenjiahan](https://github.com/chenjiahan)
* add Collapse component [\#674](https://github.com/youzan/vant/pull/674) [@chenjiahan](https://github.com/chenjiahan)
* Build: upgrade to webpack 4 [\#693](https://github.com/youzan/vant/pull/693) [@chenjiahan](https://github.com/chenjiahan)
* Popup: add lock-scroll instead of lock-on-scroll & prevent-scroll [\#688](https://github.com/youzan/vant/pull/688) [@chenjiahan](https://github.com/chenjiahan)
* Deprecate Waterfall component and add deprecate tips [\#683](https://github.com/youzan/vant/pull/683) [@chenjiahan](https://github.com/chenjiahan)
**Improvements**
* AddressEdit: add show-delete prop [\#716](https://github.com/youzan/vant/pull/716) [@chenjiahan](https://github.com/chenjiahan)
* CellSwipe: optimzie animation fluency [\#685](https://github.com/youzan/vant/pull/685) [@chenjiahan](https://github.com/chenjiahan)
* Field: support autosize maxHeight & minHeight [\#718](https://github.com/youzan/vant/pull/718) [@chenjiahan](https://github.com/chenjiahan)
* Locale: optimize i18n config [\#701](https://github.com/youzan/vant/pull/701) [@chenjiahan](https://github.com/chenjiahan)
* PullRefresh: support trigger loading animation [\#684](https://github.com/youzan/vant/pull/684) [@chenjiahan](https://github.com/chenjiahan)
* Switch: support custom size [\#723](https://github.com/youzan/vant/pull/723) [@chenjiahan](https://github.com/chenjiahan)
* Sku: add header price slot [\#705](https://github.com/youzan/vant/pull/705) [@w91](https://github.com/w91)
* Sku: optimize DOM [\#704](https://github.com/youzan/vant/pull/704) [@chenjiahan](https://github.com/chenjiahan)
* Tab: support switch tabs with swipe gestrue in the content [\#694](https://github.com/youzan/vant/pull/694) [\#695](https://github.com/youzan/vant/pull/695) [@cookfront](https://github.com/cookfront)
* Tag: adjust style [\#689](https://github.com/youzan/vant/pull/689) [@chenjiahan](https://github.com/chenjiahan)
* Toast: support Vue.use to register [\#690](https://github.com/youzan/vant/pull/690) [@chenjiahan](https://github.com/chenjiahan)
**Bug Fixes**
* fix Actionsheet bottom border missing [\#686](https://github.com/youzan/vant/pull/686) [@chenjiahan](https://github.com/chenjiahan)
* fix AddressEdit area not selected when area_code changed [\#680](https://github.com/youzan/vant/pull/680) [@chenjiahan](https://github.com/chenjiahan)
* fix Stepper value overlimit [\#691](https://github.com/youzan/vant/issues/691)
* fix Badge info font weight when selected [\#687](https://github.com/youzan/vant/pull/687) [@chenjiahan](https://github.com/chenjiahan)
### [0.12.14](https://github.com/youzan/vant/tree/v0.12.14)
`2018-03-09`
**Bug Fixes**
* Area: should reset index when area list changed [\#678](https://github.com/youzan/vant/pull/678) [@chenjiahan](https://github.com/chenjiahan)
### [0.12.13](https://github.com/youzan/vant/tree/v0.12.13)
`2018-03-09`
**Improvements**
* AddressEdit: support custom tel validator [\#673](https://github.com/youzan/vant/pull/673) [@chenjiahan](https://github.com/chenjiahan)
* Sku: add close-on-click-overlay config for sku popup [\#676](https://github.com/youzan/vant/pull/676) [@w91](https://github.com/w91)
**Bug Fixes**
* fix CouponList text max-width [\#675](https://github.com/youzan/vant/pull/675) [@chenjiahan](https://github.com/chenjiahan)
### [0.12.12](https://github.com/youzan/vant/tree/v0.12.12)
`2018-03-06`

View File

@ -0,0 +1,95 @@
## Collapse
### Install
``` javascript
import { Collapse, CollapseItem } from 'vant';
Vue.use(Collapse).use(CollapseItem);
```
### Usage
#### Basic Usage
Use `v-model` to control the name of active panels
```html
<van-collapse v-model="activeNames">
<van-collapse-item title="Title1" name="1">Content</van-collapse-item>
<van-collapse-item title="Title2" name="2">Content</van-collapse-item>
<van-collapse-item title="Title3" name="3">Content</van-collapse-item>
</van-collapse>
```
``` javascript
export default {
data() {
return {
activeNames: ['1']
};
}
};
```
#### Accordion
In accordion mode, only one panel can be expanded at the same time.
```html
<van-collapse v-model="activeName" accordion>
<van-collapse-item title="Title1" name="1">Content</van-collapse-item>
<van-collapse-item title="Title2" name="2">Content</van-collapse-item>
<van-collapse-item title="Title3" name="3">Content</van-collapse-item>
</van-collapse>
```
``` javascript
export default {
data() {
return {
activeName: '1'
};
}
};
```
#### Custom title
```html
<van-collapse v-model="activeNames">
<van-collapse-item name="1">
<div slot="title">Title1<van-icon name="question" /></div>
Content
</van-collapse-item>
<van-collapse-item title="Title2" name="2">
Content
</van-collapse-item>
</van-collapse>
```
### Collapse API
| Attribute | Description | Type | Default | Accepted Values |
|-----------|-----------|-----------|-------------|-------------|
| v-model | names of current active panels | `Array | String | Number` | - | - |
| accordion | Whether to be accordion mode | `Boolean` | `false` | - |
### Collapse Event
| Event | Description | Arguments |
|-----------|-----------|-----------|
| change | Triggered when switch panel | activeNames: `string | array` |
### CollapseItem API
| Attribute | Description | Type | Default | Accepted Values |
|-----------|-----------|-----------|-------------|-------------|
| name | Name | `String | Number` | `index` | - |
| title | Title | `String` | - | - |
### CollapseItem Slot
| name | Description |
|-----------|-----------|
| default | Content |
| title | Custom title |

View File

@ -9,7 +9,7 @@ Vue.use(DatetimePicker);
### Usage
#### Basic Usage
#### Choose DateTime
```html
<van-datetime-picker
@ -30,29 +30,57 @@ export default {
maxHour: 20,
minDate: new Date(),
maxDate: new Date(2019, 10, 1),
currentDate: new Date(2018, 0, 1)
currentDate: new Date()
};
}
};
```
#### Date Picker
#### Choose Date
```html
<van-datetime-picker
v-model="currentDate"
type="date"
:min-hour="minHour"
:max-hour="maxHour"
:min-date="minDate"
/>
```
#### Time Picker
```js
export default {
data() {
return {
currentDate: new Date()
};
}
}
```
#### Choose Year-Month
```html
<van-datetime-picker
v-model="currentDate3"
v-model="currentDate"
type="year-month"
:min-date="minDate"
/>
```
```js
export default {
data() {
return {
currentDate: new Date()
};
}
}
```
#### Choose Time
```html
<van-datetime-picker
v-model="currentDate"
type="time"
:min-hour="minHour"
:max-hour="maxHour"
@ -60,11 +88,21 @@ export default {
/>
```
```js
export default {
data() {
return {
currentDate: '12:00'
};
}
}
```
### API
| Attribute | Description | Type | Default | Accepted Values |
|-----------|-----------|-----------|-------------|-------------|
| type | Picker type | `String` | 'datetime' | 'date', 'time' |
| type | Picker type | `String` | `datetime` | `date` `time` `year-month` |
| min-date | Min date | `Date` | Ten years ago on January 1 | - |
| max-date | Max date | `Date` | Ten years later on December 31 | - |
| min-hour | Min hour | `Number` | `0` | - |

View File

@ -76,7 +76,7 @@ export default {
| cancelButtonText | Cancel button test | `String` | `Cancel` | - |
| overlay | Whether to show overlay | `Boolean` | `true` | - |
| closeOnClickOverlay | Whether to close when click overlay | `Boolean` | `false` | - |
| lockOnScroll | Whether to lock body scroll | `Boolean` | `true` | - |
| lockScroll | Whether to lock body scroll | `Boolean` | `true` | - |
#### Advanced Usage
If you need to render vue components within a dialog, you can use dialog component.
@ -130,7 +130,7 @@ export default {
| 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` | - |
| lock-scroll | Whether to lock background scroll | `Boolean` | `true` | - |
### Event

View File

@ -99,7 +99,7 @@ Filed support all native properties of input tagsuch as `maxlength`、`placeh
| disabled | Disable field | `Boolean` | `false` | - |
| error | Whether to show error info | `Boolean` | `false` | - |
| error-message | Error message | `String` | `''` | - |
| autosize | Textarea auto resize | `Boolean` | `false` | - |
| autosize | Textarea auto resizecan accpet an object, e.g. { maxHeight: 100, minHeight: 50 } | `Boolean | Object` | `false` | - |
| icon | Right side Icon name | `String` | - | - |
### Event

View File

@ -29,3 +29,9 @@ import 'vant/lib/vant-css/icon-local.css';
|-----------|-----------|-----------|-------------|-------------|
| name | Icon name | `String` | `''` | - |
| info | Info message | `String` | `''` | - |
### Event
| Event | Description | Arguments |
|-----------|-----------|-----------|
| click | Triggered when click icon | - |

View File

@ -7,7 +7,7 @@
### Features
* 48+ Reusable components
* 50+ Reusable components
* 90%+ Unit test coverage
* Extensive documentation and demos
* Support [babel-plugin-import](https://github.com/ant-design/babel-plugin-import)

View File

@ -0,0 +1,66 @@
## List
A list component to show items and control loading status.
### Install
``` javascript
import { List } from 'vant';
Vue.use(List);
```
### Usage
#### Basic Usage
```html
<van-list
v-model="loading"
:finished="finished"
@load="onLoad"
>
<van-cell v-for="item in list" :key="item" :title="item + ''" />
</van-list>
```
```js
export default {
data() {
return {
list: [],
loading: false,
finished: false
};
},
methods: {
onLoad() {
setTimeout(() => {
for (let i = 0; i < 10; i++) {
this.list.push(this.list.length + 1);
}
this.loading = false;
if (this.list.length >= 40) {
this.finished = true;
}
}, 500);
}
}
}
```
### API
| Attribute | Description | Type | Default | Accepted Values |
|-----------|-----------|-----------|-------------|-------------|
| loading | Whether to show loading infothe `load` event will not be triggered when loading | `Boolean` | `false` | - |
| finished | Whether loading is finishedthe `load` event will not be triggered when finished | `Boolean` | `false` | - |
| offset | The load event will be triggered when the distance between the scrollbar and the bottom is less than offset | `Number` | `300` | - |
| loading-text | Loading text | `String` | `Loading...` | - |
| immediate-check | Whether to check loading position immediately after mounted | `Boolean` | `true` | - |
### Event
| Event | Description | Arguments |
|-----------|-----------|-----------|
| load | Triggered when the distance between the scrollbar and the bottom is less than offset | - |

View File

@ -41,13 +41,12 @@ Use `position` prop to set popup display position
|-----------|-----------|-----------|-------------|-------------|
| v-model | Whether to show popup | `Boolean` | `false` | - |
| overlay | Whether to show overlay | `Boolean` | `true` | - |
| lock-on-scroll | Lock body scroll | `Boolean` | `false` | - |
| position | Position | `String` | - | `top` `bottom` `right` `left` |
| overlay-class | Custom overlay class | `String` | `` | - |
| overlay-style | Custom overlay style | `Object` | - | - |
| close-on-click-overlay | Close popup when click overlay | `Boolean` | `true` | - |
| transition | Transition | `String` | `popup-slide` | - |
| prevent-scroll | Prevent background scroll | `Boolean` | `false` | - |
| lock-scroll | Whether to lock background scroll | `Boolean` | `true` | - |
| get-container | Return the mount node for Popup | `Function` | - | `() => HTMLElement` |
### Event

View File

@ -1,6 +1,4 @@
## Vant
Mobile UI Component based on `Vue 2.0`
## Quickstart
### Install
@ -40,6 +38,7 @@ import 'vant/lib/vant-css/button.css';
```
#### 3. Import all components
If you configured babel-plugin-import, you won't be allowed to import all components.
```js
import Vue from 'vue';
@ -64,15 +63,3 @@ Vue.use(Vant);
```shell
vue init youzan/vue-cli-template-vant projectName
```
### Props Named Style
HTML attributes are case-insensitive, so when using non-string templates, camelCased prop names need to use their kebab-case (hyphen-delimited) equivalents.
``` html
<!-- camelCase in JavaScript -->
<van-cell isLink />
<!-- kebab-case in HTML -->
<van-cell is-link />
```

View File

@ -64,6 +64,12 @@ Vue.use(Sku);
@buy-clicked="onBuyClicked"
@add-cart="onAddCartClicked"
>
<!-- custom sku-header-price -->
<template slot="sku-header-price" slot-scope="props">
<div class="van-sku__goods-price">
<span class="van-sku__price-symbol"></span><span class="van-sku__price-num">{{ props.price }}</span> only!!!
</div>
</template>
<!-- custom sku actions -->
<template slot="sku-actions" slot-scope="props">
<div class="van-sku-actions">
@ -114,6 +120,7 @@ Vue.use(Sku);
| Name | Description |
|-----------|-----------|
| sku-header | Custom header |
| sku-header-price | Custom header price area |
| sku-body-top | Custom content before sku-group |
| sku-group | Custom sku |
| extra-sku-group | Extra custom content |

View File

@ -22,7 +22,7 @@ Use `autoplay` prop to set autoplay interval
```
#### Image Lazyload
Use [Lazyload](#/zh-CN/component/lazyload) component to lazyload image
Use [Lazyload](#/en-US/lazyload) component to lazyload image
```html
<van-swipe>

View File

@ -41,7 +41,7 @@ export default {
#### Advanced usage
```html
<van-switch :value="checked" @input="onInput" />
<van-switch :value="checked" size="36px" @input="onInput" />
```
```js
@ -71,7 +71,8 @@ export default {
|-----------|-----------|-----------|-------------|-------------|
| v-model | Check status of Switch | `Boolean` | `false` | - |
| loading | Whether to show loading icon | `Boolean` | `false` | - |
| disabled | Disable switch | `Boolean` | `false` | - |
| disabled | Whether to disable switch | `Boolean` | `false` | - |
| size | Size of switch | `String` | `30px` | - |
### Event

View File

@ -124,6 +124,18 @@ Use title slot to custom tab title
</van-tabs>
```
#### Swipeable
In swipeable mode, you can switch tabs with swipe gestrue in the content
```html
<van-tabs :active="active" swipeable>
<van-tab v-for="index in 4" :title="'tab ' + index">
content {{ index }}
</van-tab>
</van-tabs>
```
### Tabs API
| Attribute | Description | Type | Default | Accepted Values |
@ -132,6 +144,8 @@ Use title slot to custom tab title
| active | Index of active tab | `String` `Number` | `0` | - |
| duration | Toggle tab's animation time | `Number` | `0.2` | - | - |
| swipe-threshold | Set swipe tabs threshold | `Number` | `4` | - | - |
| sticky | Whether to use sticky mode | `Boolean` | `false` | - |
| swipeable | Whether to switch tabs with swipe gestrue in the content | `Boolean` | `false` | - |
### Tab API

View File

@ -1,4 +1,5 @@
## Waterfall
Note: Waterfall is deprecated and no longer maintained, please use the [List](#/zh-CN/list) component instead.
### Install

View File

@ -27,6 +27,7 @@ export default {
'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/collapse': wrapper(r => require.ensure([], () => r(require('./zh-CN/collapse.md')), 'zh-CN/collapse')),
'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')),
@ -39,6 +40,7 @@ export default {
'zh-CN/intro': wrapper(r => require.ensure([], () => r(require('./zh-CN/intro.md')), 'zh-CN/intro')),
'zh-CN/layout': wrapper(r => require.ensure([], () => r(require('./zh-CN/layout.md')), 'zh-CN/layout')),
'zh-CN/lazyload': wrapper(r => require.ensure([], () => r(require('./zh-CN/lazyload.md')), 'zh-CN/lazyload')),
'zh-CN/list': wrapper(r => require.ensure([], () => r(require('./zh-CN/list.md')), 'zh-CN/list')),
'zh-CN/loading': wrapper(r => require.ensure([], () => r(require('./zh-CN/loading.md')), 'zh-CN/loading')),
'zh-CN/nav-bar': wrapper(r => require.ensure([], () => r(require('./zh-CN/nav-bar.md')), 'zh-CN/nav-bar')),
'zh-CN/notice-bar': wrapper(r => require.ensure([], () => r(require('./zh-CN/notice-bar.md')), 'zh-CN/notice-bar')),
@ -81,6 +83,7 @@ export default {
'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/collapse': wrapper(r => require.ensure([], () => r(require('./en-US/collapse.md')), 'en-US/collapse')),
'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')),
@ -93,6 +96,7 @@ export default {
'en-US/intro': wrapper(r => require.ensure([], () => r(require('./en-US/intro.md')), 'en-US/intro')),
'en-US/layout': wrapper(r => require.ensure([], () => r(require('./en-US/layout.md')), 'en-US/layout')),
'en-US/lazyload': wrapper(r => require.ensure([], () => r(require('./en-US/lazyload.md')), 'en-US/lazyload')),
'en-US/list': wrapper(r => require.ensure([], () => r(require('./en-US/list.md')), 'en-US/list')),
'en-US/loading': wrapper(r => require.ensure([], () => r(require('./en-US/loading.md')), 'en-US/loading')),
'en-US/nav-bar': wrapper(r => require.ensure([], () => r(require('./en-US/nav-bar.md')), 'en-US/nav-bar')),
'en-US/notice-bar': wrapper(r => require.ensure([], () => r(require('./en-US/notice-bar.md')), 'en-US/notice-bar')),

View File

@ -27,7 +27,8 @@ export default {
callback: this.onClick
},
{
name: '信用卡支付'
name: '选项',
subname: '描述信息'
},
{
name: '选项',

View File

@ -15,6 +15,7 @@ Vue.use(AddressEdit);
<van-address-edit
:area-list="areaList"
show-postal
show-delete
show-set-default
show-search-result
:search-result="searchResult"
@ -61,8 +62,8 @@ export default {
| area-list | 地区列表 | `Object` | - | - |
| address-info | 收货人信息 | `Object` | `{}` | - |
| search-result | 详细地址搜索结果 | `Array` | `[]` | - |
| address-text | "地址"文案前缀 | `String` | `收货` | - |
| show-postal | 是否显示邮政编码 | `Boolean` | `false` | - |
| show-delete | 是否显示删除按钮 | `Boolean` | `false` | - |
| show-set-default | 是否显示默认地址栏 | `Boolean` | `false` | - |
| show-search-result | 是否显示搜索结果 | `Boolean` | `false` | - |
| is-saving | 是否显示保存按钮加载动画 | `Boolean` | `false` | - |
@ -101,7 +102,7 @@ export default {
| address_detail | 详细地址 | `String` |
| area_code | 地区编码,通过省市区选择获取 | `String` |
| postal_code | 邮政编码 | `String` |
| is_default | 是否为默认地址 | `String` |
| is_default | 是否为默认地址 | `Boolean` |
#### searchResult 数据格式
| key | 说明 | 类型 |
@ -110,4 +111,4 @@ export default {
| address | 详细地址 | `String` |
#### 省市县列表数据格式
请参考 [Area](#/zh-CN/component/area) 组件。
请参考 [Area](#/zh-CN/area) 组件。

View File

@ -90,7 +90,7 @@ Vue.use(Area);
}
```
完整数据见 [Area.json](https://github.com/youzan/vant/blob/dev/docs/demos/mock/area.json)
完整数据见 [Area.json](https://github.com/youzan/vant/blob/dev/docs/demos/mock/area.js)
#### 点击完成时返回的数据格式

View File

@ -15,10 +15,10 @@ Vue.use(Badge);
```html
<van-badge-group :active-key="activeKey">
<van-badge title="热销榜" @click="onClick" />
<van-badge title="花式寿司" @click="onClick" info="8" />
<van-badge title="火炽寿司" @click="onClick" info="99" />
<van-badge title="手握寿司" @click="onClick" info="199" />
<van-badge title="标签名称" @click="onClick" />
<van-badge title="标签名称" @click="onClick" info="8" />
<van-badge title="标签名称" @click="onClick" info="99" />
<van-badge title="标签名称" @click="onClick" info="199" />
</van-badge-group>
```

View File

@ -80,3 +80,9 @@ Vue.use(Button);
| loading | 是否显示为加载状态 | `Boolean` | `false` | - |
| block | 是否为块级元素 | `Boolean` | `false` | - |
| bottom-action | 是否为底部行动按钮 | `Boolean` | `false` | - |
### Event
| 事件名 | 说明 | 参数 |
|-----------|-----------|-----------|
| click | 点击按钮且按钮状态不为加载或禁用时触发 | - |

View File

@ -89,7 +89,13 @@ Vue.use(Cell).use(CellGroup);
| is-link | 是否展示右侧箭头并开启点击反馈 | `Boolean` | `false` | - |
| required | 是否显示表单必填符号 | `Boolean` | `false` | - |
### Slot
### Cell Event
| 事件名 | 说明 | 参数 |
|-----------|-----------|-----------|
| click | 点击 cell 时触发 | - |
### Cell Slot
| 名称 | 说明 |
|-----------|-----------|

View File

@ -1,5 +1,107 @@
## 更新日志
## [v1.0.1](https://github.com/youzan/vant/tree/v1.0.1) (2018-03-19)
[Full Changelog](https://github.com/youzan/vant/compare/v1.0.0...v1.0.1)
**Breaking changes**
- Waterfall 瀑布流 可以添加一个API不 [\#309](https://github.com/youzan/vant/issues/309)
**Issue**
- Tabs 标签组件 滑动切换问题 [\#725](https://github.com/youzan/vant/issues/725)
- 在引入Toast后没使用会页面上会出现一个黑块 [\#724](https://github.com/youzan/vant/issues/724)
- 在使用vant时,首次加载页面时组件尺寸大小正常,再次刷新后组件尺寸缩小 [\#717](https://github.com/youzan/vant/issues/717)
- 请问AddressEdit 地址编辑 里如何显示删除操作呢? [\#715](https://github.com/youzan/vant/issues/715)
- \[共享\]贴出城市数据放置位置,方便大家寻找 \(https://github.com/youzan/vant/blob/dev/docs/demos/mock/area.js\) [\#714](https://github.com/youzan/vant/issues/714)
- 为什么Collapse报错了 [\#710](https://github.com/youzan/vant/issues/710)
- 按照官方文档写show-action为什么会报错 [\#707](https://github.com/youzan/vant/issues/707)
- Field 组件高度自适应建议加入一个限制最高高度 [\#702](https://github.com/youzan/vant/issues/702)
- 文档有一处错误,建议修改 [\#699](https://github.com/youzan/vant/issues/699)
- feature request PullRefresh 的效果支持手动触发 [\#681](https://github.com/youzan/vant/issues/681)
- vant组件非常不错,已应用到公司项目中了,还支持ssr.但是能否加一个list组件\(带可以展开和收起那种\) [\#615](https://github.com/youzan/vant/issues/615)
- Waterfall 和 PullRefresh 在同个页面时,会有冲突 [\#596](https://github.com/youzan/vant/issues/596)
**Improvements**
- \[bugfix\] module circular dependency [\#728](https://github.com/youzan/vant/pull/728) ([chenjiahan](https://github.com/chenjiahan))
## [v1.0.0](https://github.com/youzan/vant/tree/v1.0.0) (2018-03-19)
[Full Changelog](https://github.com/youzan/vant/compare/v0.12.14...v1.0.0)
**Breaking changes**
- tab切换应该加上左右切换的操作 [\#208](https://github.com/youzan/vant/issues/208)
**Issue**
- stype scoped无法覆盖部分样式例如dialog的.van-dialog\_\_cancel [\#720](https://github.com/youzan/vant/issues/720)
- Area组件的Event怎么使用api文档上没有说明 [\#719](https://github.com/youzan/vant/issues/719)
- 搜索框的用了:show-action="true",会报错,显示不出来 [\#713](https://github.com/youzan/vant/issues/713)
- 如何改变checkBox 选中状态van-checkbox--checkedbackground-color呢 已经做了样式覆盖,确未生效 [\#712](https://github.com/youzan/vant/issues/712)
- Popup的method: click-overlay 无效invalid [\#711](https://github.com/youzan/vant/issues/711)
- Dialog作为子组件如何关闭 [\#709](https://github.com/youzan/vant/issues/709)
- checkbox, switch开关等能否通过css或者属性绑定设置尺寸 [\#708](https://github.com/youzan/vant/issues/708)
- 【文档】关于Radio组件描述残缺 [\#706](https://github.com/youzan/vant/issues/706)
- 请问一下能自己添加语言吗? [\#700](https://github.com/youzan/vant/issues/700)
- van-radio-group样式不一致 [\#697](https://github.com/youzan/vant/issues/697)
- van-nav-bar 通过 slot 定制内容时 触发click-left 或者 click-right事件出现错误 [\#696](https://github.com/youzan/vant/issues/696)
- stepper 输入达到最大值如10后面输入0变为100value值正确但是input显示100很尴尬 [\#691](https://github.com/youzan/vant/issues/691)
- build 之后 文件应用路径没有引号包裹 [\#679](https://github.com/youzan/vant/issues/679)
- 关于card组件问题 [\#677](https://github.com/youzan/vant/issues/677)
**Improvements**
- \[Improvement\] Switch: support custom size [\#723](https://github.com/youzan/vant/pull/723) ([chenjiahan](https://github.com/chenjiahan))
- \[Doc\] add click event document [\#722](https://github.com/youzan/vant/pull/722) ([chenjiahan](https://github.com/chenjiahan))
- \[Improvement\] Field: support autosize maxHeight & minHeight [\#718](https://github.com/youzan/vant/pull/718) ([chenjiahan](https://github.com/chenjiahan))
- \[Improvement\] AddressEdit: add show-delete prop [\#716](https://github.com/youzan/vant/pull/716) ([chenjiahan](https://github.com/chenjiahan))
- Sku header price slot [\#705](https://github.com/youzan/vant/pull/705) ([w91](https://github.com/w91))
- \[Improvement\] Sku: optimize DOM [\#704](https://github.com/youzan/vant/pull/704) ([chenjiahan](https://github.com/chenjiahan))
- \[Improvement\] extract component common part [\#703](https://github.com/youzan/vant/pull/703) ([chenjiahan](https://github.com/chenjiahan))
- \[Improvement\] Locale: optimize i18 config [\#701](https://github.com/youzan/vant/pull/701) ([chenjiahan](https://github.com/chenjiahan))
- \[Doc\] improve document detail [\#698](https://github.com/youzan/vant/pull/698) ([chenjiahan](https://github.com/chenjiahan))
- \[Improvement\] Tabs: use touchend event to handle swipe [\#695](https://github.com/youzan/vant/pull/695) ([cookfront](https://github.com/cookfront))
- \[new feature\] Tabs: support switch tabs with swipe gestrue in the content [\#694](https://github.com/youzan/vant/pull/694) ([cookfront](https://github.com/cookfront))
- \[Improvement\] upgrade to webpack 4 [\#693](https://github.com/youzan/vant/pull/693) ([chenjiahan](https://github.com/chenjiahan))
- \[Improvement\] Toast: support Vue.use to register [\#690](https://github.com/youzan/vant/pull/690) ([chenjiahan](https://github.com/chenjiahan))
- \[Improvement\] Tag: adjust style [\#689](https://github.com/youzan/vant/pull/689) ([chenjiahan](https://github.com/chenjiahan))
- \[breaking change\] Popup: add lockScroll instead of lockOnScroll & preventScroll [\#688](https://github.com/youzan/vant/pull/688) ([chenjiahan](https://github.com/chenjiahan))
- \[bugfix\] Badge info font weight [\#687](https://github.com/youzan/vant/pull/687) ([chenjiahan](https://github.com/chenjiahan))
- \[bugfix\] Actionsheet: border display error [\#686](https://github.com/youzan/vant/pull/686) ([chenjiahan](https://github.com/chenjiahan))
- \[Improvement\] CellSwipe: optimzie animation fluency [\#685](https://github.com/youzan/vant/pull/685) ([chenjiahan](https://github.com/chenjiahan))
- \[Improvement\] PullRefresh: support trigger loading animation [\#684](https://github.com/youzan/vant/pull/684) ([chenjiahan](https://github.com/chenjiahan))
- \[Deprecate\] add Waterfall deprecate tip [\#683](https://github.com/youzan/vant/pull/683) ([chenjiahan](https://github.com/chenjiahan))
- \[new feature\] add List component [\#682](https://github.com/youzan/vant/pull/682) ([chenjiahan](https://github.com/chenjiahan))
- \[bugfix\] AddressEdit: area code observer [\#680](https://github.com/youzan/vant/pull/680) ([chenjiahan](https://github.com/chenjiahan))
- \[new feature\] add Collapse component [\#674](https://github.com/youzan/vant/pull/674) ([chenjiahan](https://github.com/chenjiahan))
## [v0.12.14](https://github.com/youzan/vant/tree/v0.12.14) (2018-03-09)
[Full Changelog](https://github.com/youzan/vant/compare/v0.12.13...v0.12.14)
**Improvements**
- \[bugfix\] Area: should reset index when area list changed [\#678](https://github.com/youzan/vant/pull/678) ([chenjiahan](https://github.com/chenjiahan))
## [v0.12.13](https://github.com/youzan/vant/tree/v0.12.13) (2018-03-09)
[Full Changelog](https://github.com/youzan/vant/compare/v0.12.12...v0.12.13)
**Issue**
- 请问什么时候可以想vue.ydui.org里面那样弄个rem 版的 [\#672](https://github.com/youzan/vant/issues/672)
- 使用babel-plugin-import 出错 [\#671](https://github.com/youzan/vant/issues/671)
- undefined is not an object \(evaluating 't.offsetWidth'\) [\#668](https://github.com/youzan/vant/issues/668)
- 关于输入框禁用样式 [\#667](https://github.com/youzan/vant/issues/667)
- Swipe - 'change event' - Documentation [\#664](https://github.com/youzan/vant/issues/664)
- Swipe - 'no-wrap' - Enhancement [\#663](https://github.com/youzan/vant/issues/663)
- Swipe 组件希望能增加禁止自动播放的功能 [\#656](https://github.com/youzan/vant/issues/656)
**Improvements**
- \[new feature\] add close-on-click-overlay config for sku popup [\#676](https://github.com/youzan/vant/pull/676) ([w91](https://github.com/w91))
- \[bugfix\] CouponList text max-width [\#675](https://github.com/youzan/vant/pull/675) ([chenjiahan](https://github.com/chenjiahan))
- \[new feature\] AddressEdit support custom tel validator [\#673](https://github.com/youzan/vant/pull/673) ([chenjiahan](https://github.com/chenjiahan))
## [v0.12.12](https://github.com/youzan/vant/tree/v0.12.12) (2018-03-06)
[Full Changelog](https://github.com/youzan/vant/compare/v0.12.11...v0.12.12)

View File

@ -1,5 +1,65 @@
## 更新日志
### [1.0.1](https://github.com/youzan/vant/tree/v1.0.1)
`2018-03-19`
**Bug Fixes**
- 修复 create 模块循环引用导致某些情况下编译错误的问题 [\#728](https://github.com/youzan/vant/pull/728) [@chenjiahan](https://github.com/chenjiahan)
### [1.0.0](https://github.com/youzan/vant/tree/v1.0.0)
`2018-03-19`
**Breaking changes**
* 新增 List 组件 [\#682](https://github.com/youzan/vant/pull/682) [@chenjiahan](https://github.com/chenjiahan)
* 新增 Collapse 组件 [\#674](https://github.com/youzan/vant/pull/674) [@chenjiahan](https://github.com/chenjiahan)
* 构建: 升级至 webpack 4优化构建配置 [\#693](https://github.com/youzan/vant/pull/693) [@chenjiahan](https://github.com/chenjiahan)
* Popup: 新增 lock-scroll 属性,废弃 lock-on-scroll、prevent-scroll 属性 [\#688](https://github.com/youzan/vant/pull/688) [@chenjiahan](https://github.com/chenjiahan)
* Waterfall 组件不再维护,推荐使用 List 组件代替 [\#683](https://github.com/youzan/vant/pull/683) [@chenjiahan](https://github.com/chenjiahan)
**Improvements**
* AddressEdit: 新增 show-delete 属性 [\#716](https://github.com/youzan/vant/pull/716) [@chenjiahan](https://github.com/chenjiahan)
* CellSwipe: 优化 Swipe 动画流畅度 [\#685](https://github.com/youzan/vant/pull/685) [@chenjiahan](https://github.com/chenjiahan)
* Field: 支持配置 autosize 最大/最小高度 [\#718](https://github.com/youzan/vant/pull/718) [@chenjiahan](https://github.com/chenjiahan)
* Locale: 精简 i18n 配置文档 [\#701](https://github.com/youzan/vant/pull/701) [@chenjiahan](https://github.com/chenjiahan)
* PullRefresh: 支持手动触发 loading 动画 [\#684](https://github.com/youzan/vant/pull/684) [@chenjiahan](https://github.com/chenjiahan)
* Switch: 新增 size 数组,支持自定义尺寸 [\#723](https://github.com/youzan/vant/pull/723) [@chenjiahan](https://github.com/chenjiahan)
* Sku: 新增头部金额 slot [\#705](https://github.com/youzan/vant/pull/705) [@w91](https://github.com/w91)
* Sku: 优化 DOM 结构 [\#704](https://github.com/youzan/vant/pull/704) [@chenjiahan](https://github.com/chenjiahan)
* Tab: 支持通过滑动手势进行切换 [\#694](https://github.com/youzan/vant/pull/694) [\#695](https://github.com/youzan/vant/pull/695) [@cookfront](https://github.com/cookfront)
* Tag: 调整标签样式 [\#689](https://github.com/youzan/vant/pull/689) [@chenjiahan](https://github.com/chenjiahan)
* Toast: 支持通过 Vue.use 注册 [\#690](https://github.com/youzan/vant/pull/690) [@chenjiahan](https://github.com/chenjiahan)
**Bug Fixes**
* 修复 Actionsheet 下边框未展示的问题 [\#686](https://github.com/youzan/vant/pull/686) [@chenjiahan](https://github.com/chenjiahan)
* 修复 AddressEdit 在数据变更时未正确选中省市区的问题 [\#680](https://github.com/youzan/vant/pull/680) [@chenjiahan](https://github.com/chenjiahan)
* 修复 Stepper value 溢出的问题 [\#691](https://github.com/youzan/vant/issues/691)
* 修复 Badge 选中时字体粗细 [\#687](https://github.com/youzan/vant/pull/687) [@chenjiahan](https://github.com/chenjiahan)
### [0.12.14](https://github.com/youzan/vant/tree/v0.12.14)
`2018-03-09`
**Bug Fixes**
* Area: 修复 area-list 更新时未正确选中省市区的问题 [\#678](https://github.com/youzan/vant/pull/678) [@chenjiahan](https://github.com/chenjiahan)
### [0.12.13](https://github.com/youzan/vant/tree/v0.12.13)
`2018-03-09`
**Improvements**
* AddressEdit: 支持自定义手机号校验函数 [\#673](https://github.com/youzan/vant/pull/673) [@chenjiahan](https://github.com/chenjiahan)
* Sku: 新增 close-on-click-overlay 属性 [\#676](https://github.com/youzan/vant/pull/676) [@w91](https://github.com/w91)
**Bug Fixes**
* 修复 CouponList 文字截断的问题 [\#675](https://github.com/youzan/vant/pull/675) [@chenjiahan](https://github.com/chenjiahan)
### [0.12.12](https://github.com/youzan/vant/tree/v0.12.12)
`2018-03-06`

View File

@ -0,0 +1,108 @@
## Collapse 折叠面板
### 使用指南
``` javascript
import { Collapse, CollapseItem } from 'vant';
Vue.use(Collapse).use(CollapseItem);
```
### 代码演示
#### 基础用法
通过`v-model`控制展开的面板列表,`activeNames`为数组格式
```html
<van-collapse v-model="activeNames">
<van-collapse-item title="有赞微商城" name="1">
提供多样店铺模板,快速搭建网上商城
</van-collapse-item>
<van-collapse-item title="有赞零售" name="2">
网店吸粉获客、会员分层营销、一机多种收款,告别经营低效和客户流失
</van-collapse-item>
<van-collapse-item title="有赞美业" name="3">
线上拓客,随时预约,贴心顺手的开单收银
</van-collapse-item>
</van-collapse>
```
``` javascript
export default {
data() {
return {
activeNames: ['1']
};
}
};
```
#### 手风琴
通过`accordion`可以设置为手风琴模式,最多展开一个面板,此时`activeName`为字符串格式
```html
<van-collapse v-model="activeName" accordion>
<van-collapse-item title="有赞微商城" name="1">
提供多样店铺模板,快速搭建网上商城
</van-collapse-item>
<van-collapse-item title="有赞零售" name="2">
网店吸粉获客、会员分层营销、一机多种收款,告别经营低效和客户流失
</van-collapse-item>
<van-collapse-item title="有赞美业" name="3">
线上拓客,随时预约,贴心顺手的开单收银
</van-collapse-item>
</van-collapse>
```
``` javascript
export default {
data() {
return {
activeName: '1'
};
}
};
```
#### 自定义标题内容
```html
<van-collapse v-model="activeNames">
<van-collapse-item name="1">
<div slot="title">有赞微商城<van-icon name="question" /></div>
提供多样店铺模板,快速搭建网上商城
</van-collapse-item>
<van-collapse-item title="有赞零售" name="2">
网店吸粉获客、会员分层营销、一机多种收款,告别经营低效和客户流失
</van-collapse-item>
</van-collapse>
```
### Collapse API
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| v-model | 当前展开面板的 name | `Array | String | Number` | - | - |
| accordion | 是否开启手风琴模式 | `Boolean` | `false` | - |
### Collapse Event
| 事件名 | 说明 | 参数 |
|-----------|-----------|-----------|
| change | 切换面板时触发 | activeNames: `string | array` |
### CollapseItem API
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| name | 面板唯一标识符,默认为索引值 | `String | Number` | `index` | - |
| title | 标题 | `String` | - | - |
### CollapseItem Slot
| 名称 | 说明 |
|-----------|-----------|
| default | 面板内容 |
| title | 自定义标题内容 |

View File

@ -9,7 +9,7 @@ Vue.use(DatetimePicker);
### 代码演示
#### 基础用法
#### 选择完整时间
```html
<van-datetime-picker
@ -30,24 +30,52 @@ export default {
maxHour: 20,
minDate: new Date(),
maxDate: new Date(2019, 10, 1),
currentDate: new Date(2018, 0, 1)
currentDate: new Date()
};
}
};
```
#### 选择日期
#### 选择日期(年月日)
```html
<van-datetime-picker
v-model="currentDate"
type="date"
:min-hour="minHour"
:max-hour="maxHour"
:min-date="minDate"
/>
```
```js
export default {
data() {
return {
currentDate: new Date()
};
}
}
```
#### 选择日期(年月)
```html
<van-datetime-picker
v-model="currentDate"
type="year-month"
:min-date="minDate"
/>
```
```js
export default {
data() {
return {
currentDate: new Date()
};
}
}
```
#### 选择时间
```html
@ -60,11 +88,21 @@ export default {
/>
```
```js
export default {
data() {
return {
currentDate: '12:00'
};
}
}
```
### API
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| type | 组件类型 | `String` | 'datetime' | 'date', 'time' |
| type | 组件类型 | `String` | `datetime` | `date` `time` `year-month` |
| min-date | 可选的最小日期 | `Date` | 十年前的 1 月 1 日 | - |
| max-date | 可选的最大日期 | `Date` | 十年后的 12 月 31 日 | - |
| min-hour | 可选的最小小时 | `Number` | `0` | - |

View File

@ -77,7 +77,7 @@ export default {
| cancelButtonText | 取消按钮的文案 | `String` | `取消` | - |
| overlay | 是否展示蒙层 | `Boolean` | `true` | - |
| closeOnClickOverlay | 点击蒙层时是否关闭弹窗 | `Boolean` | `false` | - |
| lockOnScroll | 是否禁用背景滚动 | `Boolean` | `true` | - |
| lockScroll | 是否锁定背景滚动 | `Boolean` | `true` | - |
#### 高级用法
@ -132,7 +132,7 @@ export default {
| cancel-button-text | 取消按钮的文案 | `String` | `取消` | - |
| overlay | 是否展示蒙层 | `Boolean` | `true` | - |
| close-on-click-overlay | 点击蒙层时是否关闭弹窗 | `Boolean` | `false` | - |
| lock-on-scroll | 是否禁用背景滚动 | `Boolean` | `true` | - |
| lock-scroll | 是否锁定背景滚动 | `Boolean` | `true` | - |
### Event

View File

@ -86,7 +86,7 @@ Vue.use(Field);
placeholder="请输入留言"
rows="1"
autosize
/>
/>
</van-cell-group>
```
@ -101,7 +101,7 @@ Filed 默认支持 Input 标签所有的原生属性,比如 `maxlength`、`pla
| disabled | 是否禁用输入框 | `Boolean` | `false` | - |
| error | 输入框是否有错误 | `Boolean` | `false` | - |
| error-message | 输入框底部错误提示文案 | `String` | `''` | - |
| autosize | 高度自适应(仅支持textarea) | `Boolean` | `false` | - |
| autosize | 自适应内容高度,只对 textarea 有效,可传入对象,如 { maxHeight: 100, minHeight: 50 },单位为 px | `Boolean | Object` | `false` | - |
| icon | 输入框尾部图标 | `String` | - | Icon 组件支持的类型 |
### Event

View File

@ -30,3 +30,9 @@ import 'vant/lib/vant-css/icon-local.css';
|-----------|-----------|-----------|-------------|-------------|
| name | 图标名称 | `String` | `''` | - |
| info | 图标右上角文字提示 | `String` | `''` | - |
### Event
| 事件名 | 说明 | 参数 |
|-----------|-----------|-----------|
| click | 点击图标时触发 | - |

View File

@ -7,7 +7,7 @@
### 特性
* 48+ 个经过有赞线上业务检验的组件
* 50+ 个经过有赞线上业务检验的组件
* 单元测试覆盖率超过 90%
* 完善的文档和示例
* 支持 [babel-plugin-import](https://github.com/ant-design/babel-plugin-import)
@ -16,7 +16,7 @@
### 快速上手
请参考 [快速上手](https://www.youzanyun.com/zanui/vant#/zh-CN/component/quickstart).
请参考 [快速上手](https://www.youzanyun.com/zanui/vant#/zh-CN/quickstart).
### 贡献代码
@ -32,7 +32,7 @@
* [意见反馈](https://github.com/youzan/vant/issues)
* [加入我们](https://job.youzan.com)
* [更新日志](https://www.youzanyun.com/zanui/vant#/zh-CN/component/changelog)
* [更新日志](https://www.youzanyun.com/zanui/vant#/zh-CN/changelog)
* [React 组件库](https://www.youzanyun.com/zanui/zent)
* [微信小程序组件库](https://github.com/youzan/zanui-weapp)
* [vant-demo](https://github.com/youzan/vant-demo)

View File

@ -0,0 +1,66 @@
## List 列表
瀑布流滚动加载,用于控制长列表的展示
### 使用指南
``` javascript
import { List } from 'vant';
Vue.use(List);
```
### 代码演示
#### 基础用法
```html
<van-list
v-model="loading"
:finished="finished"
@load="onLoad"
>
<van-cell v-for="item in list" :key="item" :title="item + ''" />
</van-list>
```
```js
export default {
data() {
return {
list: [],
loading: false,
finished: false
};
},
methods: {
onLoad() {
setTimeout(() => {
for (let i = 0; i < 10; i++) {
this.list.push(this.list.length + 1);
}
this.loading = false;
if (this.list.length >= 40) {
this.finished = true;
}
}, 500);
}
}
}
```
### API
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| loading | 是否显示加载中提示,加载过程中不触发`load`事件 | `Boolean` | `false` | - |
| finished | 是否已加载完成,加载完成后不再触发`load`事件 | `Boolean` | `false` | - |
| offset | 滚动条与底部距离小于 offset 时触发`load`事件 | `Number` | `300` | - |
| loading-text | 加载中提示文案 | `String` | `加载中...` | - |
| immediate-check | 是否在初始化时立即执行滚动位置检查 | `Boolean` | `true` | - |
### Event
| 事件名 | 说明 | 参数 |
|-----------|-----------|-----------|
| load | 滚动条与底部距离小于 offset 时触发 | - |

View File

@ -34,6 +34,6 @@ Vue.use(Loading);
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| color | 颜色 | `String` | `black` | `black` `white` |
| color | 颜色 | `String` | `black` | `white` |
| type | 类型 | `String` | `circular` | `spinner` `circle` |
| size | 大小 | `String` | `30px` | - |

View File

@ -1,5 +1,5 @@
## PasswordInput 密码输入框
密码输入框组件通常与 [数字键盘](#/zh-CN/component/number-keyboard) 组件配合使用
密码输入框组件通常与 [数字键盘](#/zh-CN/number-keyboard) 组件配合使用
### 使用指南
``` javascript

View File

@ -131,7 +131,7 @@ export default {
| show-toolbar | 是否显示顶部栏 | `Boolean` | `false` | - |
| title | 顶部栏标题 | `String` | `''` | - |
| loading | 是否显示加载状态 | `Boolean` | `false` | - |
| confirm-button-text | 确认按钮文字 | `String` | `完成` | - |
| confirm-button-text | 确认按钮文字 | `String` | `确认` | - |
| cancel-button-text | 取消按钮文字 | `String` | `取消` | - |
| item-height | 选项高度 | `Number` | `44` | - |
| visible-item-count | 可见的选项个数 | `Number` | `5` | - |

View File

@ -41,13 +41,12 @@ export default {
|-----------|-----------|-----------|-------------|-------------|
| v-model | 当前组件是否显示 | `Boolean` | `false` | - |
| overlay | 是否显示背景蒙层 | `Boolean` | `true` | - |
| lock-on-scroll | 背景是否跟随滚动 | `Boolean` | `false` | - |
| lock-scroll | 是否锁定背景滚动 | `Boolean` | `true` | - |
| position | Popup 位置 | `String` | - | `top` `bottom` `right` `left` |
| overlay-class | 自定义蒙层 class | `String` | `` | - |
| overlay-style | 自定义蒙层样式 | `Object` | `` | - |
| close-on-click-overlay | 点击蒙层是否关闭 Popup | `Boolean` | `true` | - |
| transition | transition 名称 | `String` | `popup-slide` | - |
| prevent-scroll | 是否防止滚动穿透 | `Boolean` | `false` | - |
| get-container | 指定弹出层挂载的 HTML 节点 | `Function` | - | `() => HTMLElement` |
### Event

View File

@ -38,6 +38,7 @@ import 'vant/lib/vant-css/button.css';
```
#### 方式三. 导入所有组件
配置 babel-plugin-import 插件后将不允许导入所有组件的方式
```js
import Vue from 'vue';
@ -63,15 +64,3 @@ Vue.use(Vant);
```shell
vue init youzan/vue-cli-template-vant projectName
```
### Props 命名风格
Vant 文档中的 props 默认采用驼峰式命名 (camelCase)。由于 HTML 特性是不区分大小写的,如果在 HTML 中直接书写 Vue 模板,需要使用短横线分割式 (kebab-case) 的命名来传递 props
``` html
<!-- 在 JavaScript 中使用 camelCase -->
<van-cell isLink />
<!-- 在 HTML 中使用 kebab-case-->
<van-cell is-link />
```

View File

@ -64,6 +64,12 @@ Vue.use(Sku);
@buy-clicked="onBuyClicked"
@add-cart="onAddCartClicked"
>
<!-- 自定义 sku-header-price -->
<template slot="sku-header-price" slot-scope="props">
<div class="van-sku__goods-price">
<span class="van-sku__price-symbol"></span><span class="van-sku__price-num">{{ props.price }}</span> only!!!
</div>
</template>
<!-- 自定义 sku actions -->
<template slot="sku-actions" slot-scope="props">
<div class="van-sku-actions">
@ -116,6 +122,7 @@ Sku 组件默认划分好了若干区块,这些区块都定义成了 slot
| 名称 | 说明 |
|-----------|-----------|
| sku-header | 商品信息展示区,包含商品图片、名称、价格等信息 |
| sku-header-price | 自定义sku头部价格展示 |
| sku-body-top | sku展示区上方的slot无默认展示内容按需使用 |
| sku-group | 商品sku展示区 |
| extra-sku-group | 额外商品sku展示区一般用不到 |

View File

@ -30,9 +30,9 @@ export default {
}
```
#### 物流描述
#### 描述信息
通过`title``description`属性来定义物流描述信息
通过`title``description`属性来定义描述信息信息
```html
<van-steps

View File

@ -22,7 +22,7 @@ Vue.use(Swipe).use(SwipeItem);
```
#### 图片懒加载
配合 [Lazyload](#/zh-CN/component/lazyload) 组件实现图片懒加载
配合 [Lazyload](#/zh-CN/lazyload) 组件实现图片懒加载
```html
<van-swipe :autoplay="3000">

View File

@ -36,7 +36,7 @@ export default {
#### 高级用法
```html
<van-switch :value="checked" @input="onInput" />
<van-switch :value="checked" size="36px" @input="onInput" />
```
```js
@ -68,6 +68,7 @@ export default {
| v-model | 开关选中状态 | `Boolean` | `false` | - |
| loading | 是否为加载状态 | `Boolean` | `false` | - |
| disabled | 是否为禁用状态 | `Boolean` | `false` | - |
| size | 开关尺寸 | `String` | `30px` | - |
### Event

View File

@ -124,6 +124,18 @@ export default {
</van-tabs>
```
#### 滑动切换
通过`swipeable`属性可以开启滑动切换tab
```html
<van-tabs :active="active" swipeable>
<van-tab v-for="index in 4" :title="'选项 ' + index">
内容 {{ index }}
</van-tab>
</van-tabs>
```
### Tabs API
| 参数 | 说明 | 类型 | 默认值 | 可选 |
@ -133,6 +145,7 @@ export default {
| duration | 切换 tab 的动画时间 | `Number` | `0.2` | - |
| swipe-threshold | 滚动阀值,设置 Tab 超过多少个可滚动 | `Number` | `4` | - |
| sticky | 是否使用粘性定位布局 | `Boolean` | `false` | - |
| swipeable | 是否可以滑动内容切换 | `Boolean` | `false` | - |
### Tab API

View File

@ -1,4 +1,5 @@
## Waterfall 瀑布流
注意Waterfall 组件已被废弃且不再维护,请使用 [List](#/zh-CN/list) 组件代替
### 使用指南
@ -78,4 +79,3 @@ export default {
| v-waterfall-upper | 滚动到顶部, 触发执行的函数 | `Function` | - | - |
| waterfall-disabled | 在 vue 对象中表示是否禁止瀑布流触发的 key 值 | `String` | - | - |
| waterfall-offset | 触发瀑布流加载的阈值 | `Number` | `300` | - |

View File

@ -7,7 +7,9 @@
left-arrow
@click-left="onBack"
/>
<router-view />
<keep-alive>
<router-view />
</keep-alive>
</div>
</template>
@ -43,4 +45,9 @@ body {
text-transform: capitalize;
}
}
.van-doc-demo-section {
margin-top: -46px;
padding-top: 46px;
}
</style>

View File

@ -88,6 +88,10 @@ module.exports = {
path: '/circle',
title: 'Circle - 环形进度条'
},
{
path: '/collapse',
title: 'Collapse - 折叠面板'
},
{
path: '/icon',
title: 'Icon - 图标'
@ -100,6 +104,10 @@ module.exports = {
path: '/lazyload',
title: 'Lazyload - 图片懒加载'
},
{
path: '/list',
title: 'List - 列表'
},
{
path: '/loading',
title: 'Loading - 加载'
@ -315,7 +323,7 @@ module.exports = {
},
{
path: '/quickstart',
title: 'Getting Started',
title: 'Quickstart',
noExample: true
},
{
@ -374,6 +382,10 @@ module.exports = {
path: '/circle',
title: 'Circle'
},
{
path: '/collapse',
title: 'Collapse'
},
{
path: '/icon',
title: 'Icon'
@ -386,6 +398,10 @@ module.exports = {
path: '/lazyload',
title: 'Lazyload'
},
{
path: '/list',
title: 'List'
},
{
path: '/loading',
title: 'Loading'

View File

@ -5,6 +5,7 @@ import routes from './router';
import Vant, { Lazyload } from 'packages';
import VantDoc from 'vant-doc';
import 'packages/vant-css/src/index.css';
import 'packages/vant-css/src/icon-local.css';
import 'vant-doc/src/helper/touch-simulator';
import './components/nprogress.css';

View File

@ -1,6 +1,6 @@
{
"name": "vant",
"version": "0.12.13",
"version": "1.0.1",
"description": "A Vue.js 2.0 Mobile UI at YouZan",
"main": "lib/vant.js",
"style": "lib/vant-css/index.css",
@ -13,16 +13,16 @@
],
"scripts": {
"bootstrap": "yarn || npm i && cd ./packages/vant-css/ && yarn || npm i && cd ../../",
"dev": "npm run build:file && webpack-dev-server --inline --config build/webpack.config.dev.js --content-base ./",
"dev": "npm run build:file && webpack-dev-server --inline --config build/webpack.config.dev.js",
"build:file": "node build/bin/build-entry.js",
"build:components": "node build/bin/build-components.js --color",
"build:vant-css": "gulp build --gulpfile packages/vant-css/gulpfile.js --color",
"build:vant": "cross-env NODE_ENV=production webpack --progress --hide-modules --color --config build/webpack.build.js && cross-env NODE_ENV=production webpack -p --progress --hide-modules --color --config build/webpack.build.js",
"build:style-entry": "cross-env VUE_ENV=server node build/bin/build-style-entry.js",
"build:style-entry": "node build/bin/build-style-entry.js",
"build:changelog": "sh build/bin/build-changelog.sh",
"deploy": "npm run deploy:docs && npm run deploy:cdn && gh-pages -d docs/dist --remote youzan && rimraf docs/dist",
"deploy:cdn": "superman cdn /zanui/vant docs/dist/*.js docs/dist/*.css && superman cdn /zanui/vant/async_en-US docs/dist/async_en-US/*.js && superman cdn /zanui/vant/async_zh-CN docs/dist/async_zh-CN/*.js",
"deploy:docs": "rimraf docs/dist && cross-env NODE_ENV=production webpack --progress --hide-modules --config build/webpack.config.prod.js",
"deploy:docs": "rimraf docs/dist && cross-env NODE_ENV=production webpack --progress --hide-modules --config build/webpack.config.prod.js",
"dist": "npm run bootstrap && node build/bin/build-lib.js",
"lint": "./node_modules/.bin/eslint ./packages --ext .js,.vue",
"test": "karma start test/karma.conf.js --single-run",
@ -44,7 +44,7 @@
"license": "MIT",
"dependencies": {
"babel-runtime": "6.x",
"vue-lazyload": "^1.2.1"
"vue-lazyload": "^1.2.2"
},
"peerDependencies": {
"vue": ">= 2.5.0"
@ -54,57 +54,56 @@
"avoriaz": "2.0.0",
"babel-cli": "^6.26.0",
"babel-core": "^6.26.0",
"babel-loader": "^7.1.3",
"babel-loader": "^7.1.4",
"babel-plugin-transform-object-rest-spread": "^6.26.0",
"babel-plugin-transform-runtime": "^6.15.0",
"babel-polyfill": "^6.26.0",
"babel-preset-env": "^1.6.1",
"cache-loader": "^1.2.2",
"chai": "^4.1.2",
"codecov": "^3.0.0",
"cross-env": "^5.1.3",
"css-loader": "^0.28.10",
"cross-env": "^5.1.4",
"css-loader": "^0.28.11",
"dependency-tree": "^6.0.1",
"eslint": "^4.18.2",
"eslint": "^4.19.0",
"eslint-plugin-vue": "^4.3.0",
"extract-text-webpack-plugin": "3.0.2",
"extract-text-webpack-plugin": "^4.0.0-beta.0",
"fast-vue-md-loader": "^1.0.3",
"friendly-errors-webpack-plugin": "^1.6.1",
"gh-pages": "^1.0.0",
"html-webpack-plugin": "^3.0.4",
"html-webpack-plugin": "3.0.6",
"isparta-loader": "^2.0.0",
"karma": "^1.7.1",
"karma": "^2.0.0",
"karma-chrome-launcher": "^2.2.0",
"karma-coverage": "^1.1.1",
"karma-mocha": "^1.3.0",
"karma-phantomjs-launcher": "^1.0.4",
"karma-sinon-chai": "^1.3.2",
"karma-spec-reporter": "^0.0.32",
"karma-webpack": "^2.0.9",
"mocha": "^4.0.1",
"postcss": "^6.0.19",
"karma-webpack": "^2.0.13",
"mocha": "^5.0.4",
"postcss": "^6.0.20",
"postcss-calc": "^6.0.0",
"postcss-easy-import": "^3.0.0",
"postcss-loader": "^2.1.1",
"postcss-loader": "^2.1.2",
"precss": "2.0.0",
"progress-bar-webpack-plugin": "^1.11.0",
"rimraf": "^2.5.4",
"shelljs": "^0.8.1",
"sinon": "^2.4.1",
"sinon-chai": "^2.12.0",
"style-loader": "^0.20.2",
"style-loader": "^0.20.3",
"uppercamelcase": "^3.0.0",
"url-loader": "^1.0.1",
"vant-doc": "1.0.4",
"vue": "^2.5.13",
"vue-loader": "^14.1.1",
"vue": "2.5.16",
"vue-loader": "^14.2.1",
"vue-router": "^3.0.1",
"vue-sfc-compiler": "^0.0.8",
"vue-style-loader": "^4.0.2",
"vue-template-compiler": "^2.5.13",
"vue-template-compiler": "2.5.16",
"vue-template-es2015-compiler": "^1.6.0",
"webpack": "^3.11.0",
"webpack-dev-server": "2.11.1",
"webpack": "^4.1.1",
"webpack-cli": "^2.0.12",
"webpack-dev-server": "3.1.1",
"webpack-merge": "^4.1.2"
}
}

View File

@ -5,7 +5,7 @@
<div v-text="title" />
<icon name="close" @click.stop="$emit('input', false)" />
</div>
<ul v-if="!title" class="van-actionsheet__list">
<ul v-if="!title" class="van-actionsheet__list van-hairline--bottom">
<li
v-for="(item, index) in actions"
:key="index"
@ -34,11 +34,11 @@
</template>
<script>
import { create } from '../utils';
import create from '../utils/create';
import Popup from '../mixins/popup';
export default create({
name: 'van-actionsheet',
name: 'actionsheet',
mixins: [Popup],

View File

@ -1,8 +1,8 @@
<template>
<div ref="root">
<field
:label="$t('label.address')"
:placeholder="$t('placeholder.address')"
:label="$t('label')"
:placeholder="$t('placeholder')"
maxlength="200"
type="textarea"
autosize
@ -11,8 +11,8 @@
:error="isError"
:on-icon-click="onIconClick"
@input="$emit('input', $event)"
@focus="handleFocus"
@blur="handleBlur"
@focus="onFocus"
@blur="onBlur"
>
<div slot="icon">
<span v-if="showIcon && isAndroid" class="van-address-edit-detail__finish-edit">{{ $t('complete') }}</span>
@ -39,19 +39,15 @@
</template>
<script>
import { create } from '../utils';
import create from '../utils/create';
import Field from '../field';
import Cell from '../cell';
import CellGroup from '../cell-group';
import { isAndroid } from '../utils';
export default create({
name: 'van-address-edit-detail',
name: 'address-edit-detail',
components: {
Field,
Cell,
CellGroup
Field
},
props: {
@ -79,13 +75,13 @@ export default create({
},
methods: {
handleFocus(e) {
onFocus(e) {
this.isFocused = true;
this.$emit('focus', e);
this.$refs.root.scrollIntoView();
},
handleBlur(e) {
onBlur(e) {
// wait for click event finished
setTimeout(() => {
this.isFocused = false;

View File

@ -3,32 +3,37 @@
<cell-group>
<field
maxlength="15"
:placeholder="$t('placeholder.name')"
:label="$t('label.name', computedAddressText)"
v-model="currentInfo.name"
:placeholder="$t('name')"
:label="$t('label.name')"
v-model="data.name"
:error="errorInfo.name"
@focus="onFocus('name')"
/>
<field
type="tel"
:label="$t('label.tel')"
:placeholder="$t('placeholder.tel')"
v-model="currentInfo.tel"
:label="$t('tel')"
:placeholder="$t('telPlaceholder')"
v-model="data.tel"
:error="errorInfo.tel"
@focus="onFocus('tel')"
/>
<cell class="van-address-edit__area" :title="$t('areaTitle')" @click="showAreaSelect = true">
<span>{{ currentInfo.province || $t('placeholder.province') }}</span>
<span>{{ currentInfo.city || $t('placeholder.city') }}</span>
<span>{{ currentInfo.county || $t('placeholder.county') }}</span>
<cell
clickable
class="van-address-edit__area"
:title="$t('area')"
@click="showArea = true"
>
<span>{{ data.province || $t('province') }}</span>
<span>{{ data.city || $t('city') }}</span>
<span>{{ data.county || $t('county') }}</span>
</cell>
<address-edit-detail
:value="currentInfo.address_detail"
:value="data.address_detail"
:is-error="errorInfo.address_detail"
:show-search-result="showSearchResult"
:search-result="searchResult"
@focus="onFocus('address_detail')"
@blur="onDetailBlur"
@blur="detailFocused = false"
@input="onChangeDetail"
@select-search="$emit('select-search', $event)"
/>
@ -38,7 +43,7 @@
type="tel"
:label="$t('label.postal')"
:placeholder="$t('placeholder.postal')"
v-model="currentInfo.postal_code"
v-model="data.postal_code"
maxlength="6"
class="van-hairline--top"
:error="errorInfo.postal_code"
@ -48,25 +53,26 @@
<switch-cell
v-if="showSetDefault"
v-show="!hideBottomFields"
v-model="currentInfo.is_default"
:title="$t('defaultAddress', computedAddressText)"
v-model="data.is_default"
:title="$t('defaultAddress')"
/>
</cell-group>
<div v-show="!hideBottomFields" class="van-address-edit__buttons">
<van-button block :loading="isSaving" @click="onSaveAddress" type="primary">
<van-button block :loading="isSaving" @click="onSave" type="primary">
{{ $t('save') }}
</van-button>
<van-button block :loading="isDeleting" @click="onDeleteAddress" v-if="isEdit">
{{ $t('deleteAddress', computedAddressText) }}
<van-button block :loading="isDeleting" @click="onDelete" v-if="isEdit">
{{ $t('deleteAddress') }}
</van-button>
</div>
<popup v-model="showAreaSelect" position="bottom">
<popup v-model="showArea" position="bottom">
<van-area
ref="area"
:value="currentInfo.area_code"
:loading="!areaListLoaded"
:value="data.area_code"
:area-list="areaList"
@confirm="onAreaConfirm"
@cancel="showAreaSelect = false"
@cancel="showArea = false"
/>
</popup>
</div>
@ -74,10 +80,9 @@
<script>
/* eslint-disable camelcase */
import { create } from '../utils';
import create from '../utils/create';
import { isObj } from '../utils';
import Field from '../field';
import Cell from '../cell';
import CellGroup from '../cell-group';
import VanButton from '../button';
import Popup from '../popup';
import Toast from '../toast';
@ -87,17 +92,27 @@ import AddressEditDetail from './Detail';
import SwitchCell from '../switch-cell';
import validateMobile from '../utils/validate/mobile';
const defaultAddress = {
name: '',
tel: '',
province: '',
city: '',
county: '',
area_code: '',
postal_code: '',
address_detail: '',
is_default: false
};
export default create({
name: 'van-address-edit',
name: 'address-edit',
components: {
Field,
Cell,
CellGroup,
SwitchCell,
VanButton,
Popup,
VanArea,
VanButton,
SwitchCell,
AddressEditDetail
},
@ -105,23 +120,13 @@ export default create({
isSaving: Boolean,
isDeleting: Boolean,
areaList: Object,
showDelete: Boolean,
showPostal: Boolean,
showSetDefault: Boolean,
showSearchResult: Boolean,
addressText: String,
addressInfo: {
type: Object,
default: () => ({
name: '',
tel: '',
province: '',
city: '',
county: '',
area_code: '',
postal_code: '',
address_detail: '',
is_default: false
})
default: () => ({ ...defaultAddress })
},
searchResult: {
type: Array,
@ -135,9 +140,11 @@ export default create({
data() {
return {
showAreaSelect: false,
currentInfo: this.addressInfo,
isEdit: !!this.addressInfo.id,
showArea: false,
data: {
...defaultAddress,
...this.addressInfo
},
detailFocused: false,
errorInfo: {
name: false,
@ -148,27 +155,43 @@ export default create({
};
},
watch: {
addressInfo: {
handler(val) {
this.currentInfo = val;
this.isEdit = !!val.id;
},
deep: true
}
},
computed: {
// hide bottom field when use search && detail get focused
hideBottomFields() {
return this.searchResult.length && this.detailFocused;
},
computedAddressText() {
return this.addressText || this.$t('addressText');
areaListLoaded() {
return isObj(this.areaList) && Object.keys(this.areaList).length;
},
isEdit() {
return this.showDelete || !!this.data.id;
}
},
watch: {
addressInfo: {
handler(val) {
this.data = {
...defaultAddress,
...val
};
this.setAreaCode(val.area_code);
},
deep: true
},
areaList() {
this.setAreaCode(this.data.area_code);
}
},
created() {
this.setAreaCode(this.data.area_code);
},
methods: {
onFocus(key) {
this.errorInfo[key] = false;
@ -176,34 +199,32 @@ export default create({
this.$emit('focus', key);
},
onDetailBlur() {
this.detailFocused = false;
},
onChangeDetail(val) {
this.currentInfo.address_detail = val;
this.data.address_detail = val;
this.$emit('change-detail', val);
},
onAreaConfirm(values) {
if (values.length !== 3 || +values[0].code === -1 || +values[1].code === -1 || +values[2].code === -1) {
return Toast(this.$t('areaWrong'));
if (values.length !== 3 || values.some(value => +value.code === -1)) {
return Toast(this.$t('areaEmpty'));
}
this.data.area_code = values[2].code;
this.assignAreaValues(values);
this.showAreaSelect = false;
this.showArea = false;
this.$emit('change-area', values);
},
assignAreaValues(values) {
Object.assign(this.currentInfo, {
province: values[0].name,
city: values[1].name,
county: values[2].name,
area_code: values[2].code
});
if (values.length >= 3) {
Object.assign(this.data, {
province: values[0].name,
city: values[1].name,
county: values[2].name
});
}
},
onSaveAddress() {
onSave() {
const items = [
'name',
'tel',
@ -225,21 +246,21 @@ export default create({
});
if (isValid && !this.isSaving) {
this.$emit('save', this.currentInfo);
this.$emit('save', this.data);
}
},
getErrorMessageByKey(key) {
const value = this.currentInfo[key];
const value = this.data[key];
const { $t } = this;
switch (key) {
case 'name':
return value ? value.length <= 15 ? '' : $t('nameOverlimit') : $t('nameEmpty');
case 'tel':
return this.telValidator(value) ? '' : $t('telWrong');
return this.telValidator(value) ? '' : $t('telInvalid');
case 'area_code':
return value ? +value !== -1 ? '' : $t('areaWrong') : $t('areaEmpty');
return value && +value !== -1 ? '' : $t('areaEmpty');
case 'address_detail':
return value ? value.length <= 200 ? '' : $t('addressOverlimit') : $t('addressEmpty');
case 'postal_code':
@ -247,15 +268,15 @@ export default create({
}
},
onDeleteAddress() {
onDelete() {
if (this.isDeleting) {
return;
}
Dialog.confirm({
message: this.$t('confirmDelete', this.computedAddressText)
message: this.$t('confirmDelete')
}).then(() => {
this.$emit('delete', this.currentInfo);
this.$emit('delete', this.data);
});
},
@ -267,7 +288,7 @@ export default create({
// set area code to area component
setAreaCode(code) {
this.currentInfo.area_code = code;
this.data.area_code = code || '';
this.$nextTick(() => {
this.$nextTick(() => {
const { area } = this.$refs;

View File

@ -13,28 +13,24 @@
</radio-group>
<cell
icon="add"
class="van-address-list__add van-hairline--top"
@click="$emit('add')"
:title="addButtonText || $t('add')"
is-link
class="van-address-list__add van-hairline--top"
:title="addButtonText || $t('add')"
@click="$emit('add')"
/>
</div>
</template>
<script>
import { create } from '../utils';
import Cell from '../cell';
import CellGroup from '../cell-group';
import create from '../utils/create';
import Radio from '../radio';
import RadioGroup from '../radio-group';
export default create({
name: 'van-address-list',
name: 'address-list',
components: {
Cell,
Radio,
CellGroup,
RadioGroup
},

View File

@ -16,11 +16,12 @@
</template>
<script>
import { create, isObj } from '../utils';
import create from '../utils/create';
import Picker from '../picker';
import { isObj } from '../utils';
export default create({
name: 'van-area',
name: 'area',
components: {
Picker
@ -82,6 +83,10 @@ export default create({
watch: {
value() {
this.setIndex();
},
areaList() {
this.setIndex();
}
},

View File

@ -5,10 +5,10 @@
</template>
<script>
import { create } from '../utils';
import create from '../utils/create';
export default create({
name: 'van-badge-group',
name: 'badge-group',
props: {
activeKey: {

View File

@ -6,10 +6,10 @@
</template>
<script>
import { create } from '../utils';
import create from '../utils/create';
export default create({
name: 'van-badge',
name: 'badge',
props: {
url: String,

View File

@ -24,10 +24,10 @@
</template>
<script>
import { create } from '../utils';
import create from '../utils/create';
export default create({
name: 'van-button',
name: 'button',
props: {
text: String,

View File

@ -27,10 +27,10 @@
</template>
<script>
import { create } from '../utils';
import create from '../utils/create';
export default create({
name: 'van-card',
name: 'card',
props: {
thumb: String,

View File

@ -5,10 +5,10 @@
</template>
<script>
import { create } from '../utils';
import create from '../utils/create-basic';
export default create({
name: 'van-cell-group',
name: 'cell-group',
props: {
border: {

View File

@ -21,11 +21,13 @@
</template>
<script>
import { create } from '../utils';
import create from '../utils/create';
import Clickoutside from '../utils/clickoutside';
const THRESHOLD = 0.15;
export default create({
name: 'van-cell-swipe',
name: 'cell-swipe',
props: {
onClose: Function,
@ -45,14 +47,16 @@ export default create({
data() {
return {
offset: 0
offset: 0,
draging: false
};
},
computed: {
wrapperStyle() {
return {
transform: `translate3d(${this.offset}px, 0, 0)`
transform: `translate3d(${this.offset}px, 0, 0)`,
transition: this.draging ? 'none' : '.6s cubic-bezier(0.18, 0.89, 0.32, 1)'
};
}
},
@ -70,16 +74,19 @@ export default create({
swipeMove(offset = 0) {
this.offset = offset;
offset && (this.swiping = true);
!offset && (this.opened = false);
},
swipeLeaveTransition(direction) {
const { offset, leftWidth, rightWidth } = this;
const threshold = this.opened ? (1 - THRESHOLD) : THRESHOLD;
// right
if (direction > 0 && -offset > rightWidth * 0.4 && rightWidth > 0) {
if (direction > 0 && -offset > rightWidth * threshold && rightWidth > 0) {
this.swipeMove(-rightWidth);
this.resetSwipeStatus();
// left
} else if (direction < 0 && offset > leftWidth * 0.4 && leftWidth > 0) {
} else if (direction < 0 && offset > leftWidth * threshold && leftWidth > 0) {
this.swipeMove(leftWidth);
this.resetSwipeStatus();
} else {
@ -88,17 +95,16 @@ export default create({
},
startDrag(event) {
this.draging = true;
this.startX = event.touches[0].pageX;
this.startY = event.touches[0].pageY;
if (this.opened) {
this.startX -= this.offset;
}
},
onDrag(event) {
if (this.opened) {
!this.swiping && this.swipeMove();
this.opened = false;
return;
}
const offsetTop = event.touches[0].pageY - this.startY;
const offsetLeft = event.touches[0].pageX - this.startX;
if ((offsetLeft < 0 && -offsetLeft > this.rightWidth) ||
@ -118,6 +124,7 @@ export default create({
},
endDrag() {
this.draging = false;
if (this.swiping) {
this.swipeLeaveTransition(this.offset > 0 ? -1 : 1);
};

View File

@ -37,11 +37,16 @@
</template>
<script>
import { create } from '../utils';
import Icon from '../icon';
import RouterLink from '../mixins/router-link';
import create from '../utils/create-basic';
export default create({
name: 'van-cell',
name: 'cell',
components: {
Icon
},
mixins: [RouterLink],

View File

@ -5,10 +5,10 @@
</template>
<script>
import { create } from '../utils';
import create from '../utils/create';
export default create({
name: 'van-checkbox-group',
name: 'checkbox-group',
props: {
value: {},

View File

@ -4,10 +4,10 @@
name="success"
class="van-checkbox__icon"
:class="[
`van-checkbox--${shape}`,
{ 'van-checkbox--disabled': isDisabled },
{ 'van-checkbox--checked': isChecked }
]"
`van-checkbox--${shape}`, {
'van-checkbox--disabled': isDisabled,
'van-checkbox--checked': isChecked
}]"
@click="onClick"
/>
<span class="van-checkbox__label" @click="onClick('label')">
@ -17,11 +17,12 @@
</template>
<script>
import { create, isDef } from '../utils';
import create from '../utils/create';
import { isDef } from '../utils';
import findParent from '../mixins/find-parent';
export default create({
name: 'van-checkbox',
name: 'checkbox',
mixins: [findParent],

View File

@ -11,11 +11,11 @@
</template>
<script>
import { create } from '../utils';
import create from '../utils/create';
import { raf, cancel } from '../utils/raf';
export default create({
name: 'van-circle',
name: 'circle',
props: {
text: String,

View File

@ -9,10 +9,10 @@
</template>
<script>
import { create } from '../utils';
import create from '../utils/create';
export default create({
name: 'van-col',
name: 'col',
props: {
span: [Number, String],

View File

@ -0,0 +1,71 @@
<template>
<div
class="van-collapse-item"
:class="{
'van-hairline--top': index,
'van-collapse-item--expanded': expanded
}"
>
<cell class="van-collapse-item__title" is-link @click="onClick">
<slot name="title">{{ title }}</slot>
</cell>
<div class="van-collapse-item__content" v-show="expanded">
<slot />
</div>
</div>
</template>
<script>
import findParent from '../mixins/find-parent';
import create from '../utils/create';
import { isDef } from '../utils';
export default create({
name: 'collapse-item',
mixins: [findParent],
props: {
name: [String, Number],
title: String
},
computed: {
items() {
return this.parentGroup.items;
},
index() {
return this.items.indexOf(this);
},
currentName() {
return isDef(this.name) ? this.name : this.index;
},
expanded() {
const { activeNames } = this.parentGroup;
return this.parentGroup.accordion
? activeNames === this.currentName
: activeNames.some(name => name === this.currentName);
}
},
created() {
this.findParentByName('van-collapse');
this.items.push(this);
},
destroyed() {
this.items.splice(this.index, 1);
},
methods: {
onClick() {
const { parentGroup } = this;
const name = parentGroup.accordion && this.currentName === parentGroup.activeNames ? '' : this.currentName;
this.parentGroup.switch(name, !this.expanded);
}
}
});
</script>

View File

@ -0,0 +1,41 @@
<template>
<div class="van-collapse van-hairline--top-bottom">
<slot />
</div>
</template>
<script>
import create from '../utils/create';
export default create({
name: 'collapse',
model: {
prop: 'activeNames'
},
props: {
accordion: Boolean,
activeNames: [String, Number, Array]
},
data() {
return {
items: []
};
},
methods: {
switch(name, expanded) {
const { activeNames } = this;
if (!this.accordion) {
name = expanded
? activeNames.concat(name)
: activeNames.filter(activeName => activeName !== name);
}
this.$emit('change', name);
this.$emit('input', name);
}
}
});
</script>

View File

@ -8,7 +8,7 @@
<template v-else-if="type === 'edit'">
<icon class="van-contact-card__icon" name="contact" />
<div class="van-contact-card__text">
<div>{{ $t('name') }}{{ name }}</div>
<div>{{ $t('contact') }}{{ name }}</div>
<div>{{ $t('tel') }}{{ tel }}</div>
</div>
</template>
@ -18,10 +18,10 @@
</template>
<script>
import { create } from '../utils';
import create from '../utils/create';
export default create({
name: 'van-contact-card',
name: 'contact-card',
props: {
tel: String,

View File

@ -2,15 +2,15 @@
<div class="van-contact-edit">
<cell-group>
<field
v-model="currentInfo.name"
v-model="data.name"
maxlength="30"
:label="$t('name')"
:placeholder="$t('namePlaceholder')"
:label="$t('contact')"
:placeholder="$t('name')"
:error="errorInfo.name"
@focus="onFocus('name')"
/>
<field
v-model="currentInfo.tel"
v-model="data.tel"
type="tel"
:label="$t('tel')"
:placeholder="$t('telPlaceholder')"
@ -28,19 +28,17 @@
<script>
import Field from '../field';
import VanButton from '../button';
import CellGroup from '../cell-group';
import Dialog from '../dialog';
import Toast from '../toast';
import validateMobile from '../utils/validate/mobile';
import { create } from '../utils';
import create from '../utils/create';
export default create({
name: 'van-contact-edit',
name: 'contact-edit',
components: {
Field,
VanButton,
CellGroup
VanButton
},
props: {
@ -63,7 +61,7 @@ export default create({
data() {
return {
currentInfo: this.contactInfo,
data: this.contactInfo,
errorInfo: {
name: false,
tel: false
@ -73,7 +71,7 @@ export default create({
watch: {
contactInfo(val) {
this.currentInfo = val;
this.data = val;
}
},
@ -83,7 +81,7 @@ export default create({
},
getErrorMessageByKey(key) {
const value = this.currentInfo[key];
const value = this.data[key];
switch (key) {
case 'name':
return value ? value.length <= 15 ? '' : this.$t('nameOverlimit') : this.$t('nameEmpty');
@ -108,7 +106,7 @@ export default create({
});
if (isValid && !this.isSaving) {
this.$emit('save', this.currentInfo);
this.$emit('save', this.data);
}
},
@ -120,7 +118,7 @@ export default create({
Dialog.confirm({
message: this.$t('confirmDelete')
}).then(() => {
this.$emit('delete', this.currentInfo);
this.$emit('delete', this.data);
});
}
}

View File

@ -4,7 +4,7 @@
<cell-group>
<cell v-for="(item, index) in list" :key="item.id" is-link>
<radio :name="item.id" @click="$emit('select', item, index)">
<p class="van-contact-list__text">{{ $t('name') }}{{ item.name }}</p>
<p class="van-contact-list__text">{{ $t('contact') }}{{ item.name }}</p>
<p class="van-contact-list__text">{{ $t('tel') }}{{ item.tel }}</p>
</radio>
<icon slot="right-icon" name="edit" class="van-contact-list__edit" @click="$emit('edit', item, index)" />
@ -13,28 +13,24 @@
</radio-group>
<cell
icon="add"
class="van-contact-list__add van-hairline--top"
@click="$emit('add')"
:title="addText || $t('addText')"
is-link
class="van-contact-list__add van-hairline--top"
:title="addText || $t('addText')"
@click="$emit('add')"
/>
</div>
</template>
<script>
import Cell from '../cell';
import Radio from '../radio';
import CellGroup from '../cell-group';
import RadioGroup from '../radio-group';
import { create } from '../utils';
import create from '../utils/create';
export default create({
name: 'van-contact-list',
name: 'contact-list',
components: {
Cell,
Radio,
CellGroup,
RadioGroup
},

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