Merge remote-tracking branch 'upstream/dev' into dev

This commit is contained in:
niunai 2017-09-04 11:40:11 +08:00
commit c86ee5881d
110 changed files with 4489 additions and 869 deletions

View File

@ -1,4 +1,4 @@
var Components = require('../../components.json');
var Components = require('./get-components')();
var fs = require('fs');
var render = require('json-templater/string');
var uppercamelcase = require('uppercamelcase');
@ -34,20 +34,17 @@ export {
};
export default {
install,
version,
{{list}}
version
};
`;
delete Components.font;
var ComponentNames = Object.keys(Components);
var includeComponentTemplate = [];
var installTemplate = [];
var listTemplate = [];
ComponentNames.forEach(name => {
Components.forEach(name => {
var componentName = uppercamelcase(name);
includeComponentTemplate.push(render(IMPORT_TEMPLATE, {

View File

@ -12,7 +12,7 @@
const fs = require('fs');
const path = require('path');
const components = require('../../components.json');
const components = require('./get-components')();
const chalk = require('chalk');
require('shelljs/global');
@ -38,7 +38,7 @@ log('Finished', 'build:vant-css');
// 5. build style entrys
log('Starting', 'build:style-entries');
Object.keys(components).forEach((componentName) => {
components.forEach((componentName) => {
const dir = path.join(__dirname, '../../lib/', componentName, '/style');
const file = path.join(dir, 'index.js');
const cssPath = path.join(__dirname, '../../lib/vant-css/', `${componentName}.css`);

View File

@ -0,0 +1,8 @@
const fs = require('fs');
const path = require('path');
module.exports = function() {
const dirs = fs.readdirSync(path.resolve(__dirname, '../../packages'));
const excludes = ['index.js', 'vant-css', 'mixins', 'utils'];
return dirs.filter(dirName => excludes.indexOf(dirName) === -1)
}

View File

@ -28,21 +28,4 @@ gulp.task('copy', function(callback) {
});
});
// 添加到 components.json
gulp.task('addComponents', function(callback) {
const componentsFile = require('../../components.json');
if (componentsFile[name]) {
console.error(`${name} 已存在.`);
process.exit(1);
}
componentsFile[name] = `./packages/${name}/index.js`;
fileSave(path.join(__dirname, '../../components.json'))
.write(JSON.stringify(componentsFile, null, ' '), 'utf8')
.end('\n');
gutil.log('-------> components.json文件更新成功');
gutil.log(gutil.colors.yellow('-------> 请无视下面的make报错'));
});
runSequence('copy', 'addComponents');
runSequence('copy');

View File

@ -1,16 +0,0 @@
const path = require('path');
const docConfig = require('../docs/src/doc.config');
const { extractExample } = require('zan-doc/src/helper');
function extract(watch = false) {
extractExample({
src: path.resolve(__dirname, '../docs/examples-docs'),
dist: path.resolve(__dirname, '../docs/examples-dist'),
nav: docConfig['zh-CN'].nav,
watch
});
}
module.exports = function watch(isProduction) {
extract(!isProduction);
};

View File

@ -6,11 +6,20 @@ const HtmlWebpackPlugin = require('html-webpack-plugin');
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin');
const isProduction = process.env.NODE_ENV === 'production';
const docConfig = require('../docs/src/doc.config');
const { extractExample } = require('zan-doc/src/helper');
const styleLoaders = [
{ loader: 'css-loader' },
{ loader: 'postcss-loader', options: { sourceMap: true } }
];
require('./genExamples')(isProduction);
// extract [components].vue from [components].md
extractExample({
src: path.resolve(__dirname, '../docs/examples-docs'),
dist: path.resolve(__dirname, '../docs/examples-dist'),
nav: docConfig['zh-CN'].nav,
watch: !isProduction
});
module.exports = {
entry: {
@ -25,6 +34,7 @@ module.exports = {
chunkFilename: 'async.[name].js'
},
devServer: {
host: '0.0.0.0',
historyApiFallback: {
rewrites: [
{ from: /^\/zanui\/vue\/examples/, to: '/examples.html' },
@ -51,6 +61,7 @@ module.exports = {
{
loader: 'vue-loader',
options: {
preserveWhitespace: false,
loaders: {
postcss: ExtractTextPlugin.extract({
use: styleLoaders,
@ -104,7 +115,7 @@ module.exports = {
},
render: function(tokens, idx) {
return tokens[idx].nesting === 1
return tokens[idx].nesting === 1
? `<demo-block class="demo-box"><div class="highlight" slot="highlight"å>`
:`</div></demo-block>\n`;
}

View File

@ -1,40 +0,0 @@
{
"button": "./packages/button/index.js",
"switch": "./packages/switch/index.js",
"field": "./packages/field/index.js",
"radio": "./packages/radio/index.js",
"cell": "./packages/cell/index.js",
"icon": "./packages/icon/index.js",
"cell-group": "./packages/cell-group/index.js",
"cell-swipe": "./packages/cell-swipe/index.js",
"popup": "./packages/popup/index.js",
"dialog": "./packages/dialog/index.js",
"picker": "./packages/picker/index.js",
"radio-group": "./packages/radio-group/index.js",
"waterfall": "./packages/waterfall/index.js",
"loading": "./packages/loading/index.js",
"panel": "./packages/panel/index.js",
"card": "./packages/card/index.js",
"steps": "./packages/steps/index.js",
"tag": "./packages/tag/index.js",
"checkbox": "./packages/checkbox/index.js",
"checkbox-group": "./packages/checkbox-group/index.js",
"badge-group": "./packages/badge-group/index.js",
"badge": "./packages/badge/index.js",
"search": "./packages/search/index.js",
"step": "./packages/step/index.js",
"tabs": "./packages/tabs/index.js",
"tab": "./packages/tab/index.js",
"lazyload": "./packages/lazyload/index.js",
"image-preview": "./packages/image-preview/index.js",
"col": "./packages/col/index.js",
"row": "./packages/row/index.js",
"actionsheet": "./packages/actionsheet/index.js",
"quantity": "./packages/quantity/index.js",
"progress": "./packages/progress/index.js",
"toast": "./packages/toast/index.js",
"uploader": "./packages/uploader/index.js",
"swipe": "./packages/swipe/index.js",
"swipe-item": "./packages/swipe-item/index.js",
"datetime-picker": "./packages/datetime-picker/index.js"
}

View File

@ -1,29 +1,36 @@
<style>
.demo-badge {
.badge-group-wrapper {
padding: 30px 20px;
.van-badge-group {
width: auto;
margin: 0 15px;
padding: 20px 0;
background-color: #fff;
&::after {
display: none;
}
}
.van-badge-group {
.van-badge {
width: 85px;
margin: 0 auto;
}
}
</style>
<script>
export default {
data() {
return {
activeKey: '2'
};
},
methods: {
onItemClick(e, data) {
this.activeKey = data.mark;
}
export default {
data() {
return {
activeKey: 0
};
},
methods: {
onClick(key) {
this.activeKey = key;
}
};
}
};
</script>
## Badge 徽章
@ -39,48 +46,44 @@ Vue.component(Badge.name, Badge);
#### 基础用法
默认情况下激活第一个`badge`
通过在`van-badge-group`上设置`active-key`属性来控制选中的`badge`
:::demo 基础用法
```html
<div class="badge-group-wrapper">
<van-badge-group>
<van-badge title="热销榜" info="8" url="http://baidu.com" @click="onItemClick"></van-badge>
<van-badge title="花式寿司" info="99" @click="onItemClick"></van-badge>
<van-badge title="火炽寿司" @click="onItemClick"></van-badge>
<van-badge title="手握寿司" info="199" @click="onItemClick"></van-badge>
</van-badge-group>
</div>
<van-badge-group :active-key="activeKey">
<van-badge title="热销榜" @click="onClick"></van-badge>
<van-badge title="花式寿司" @click="onClick" info="8"></van-badge>
<van-badge title="火炽寿司" @click="onClick" info="99"></van-badge>
<van-badge title="手握寿司" @click="onClick" info="199"></van-badge>
</van-badge-group>
```
``` javascript
export default {
data() {
return {
activeKey: 0
};
},
methods: {
onClick(key) {
this.activeKey = key;
}
}
};
```
:::
#### 选中某个badge
如果想默认选中某个`badge`,你可以在`van-badge-group`上设置`activeKey`属性,属性值为对应的`badge`索引。
### BadgeGroup API
:::demo 选中某个badge
```html
<div class="badge-group-wrapper">
<van-badge-group :active-key="2">
<van-badge title="热销榜" info="8" url="http://baidu.com" @click="onItemClick"></van-badge>
<van-badge title="花式寿司" info="99" @click="onItemClick"></van-badge>
<van-badge title="火炽寿司" @click="onItemClick"></van-badge>
<van-badge title="手握寿司" info="199" @click="onItemClick"></van-badge>
</van-badge-group>
</div>
```
:::
### z-badge-group API
| 参数 | 说明 | 类型 | 默认值 | 必须 |
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| active-key | 激活的`badge`的索引 | `string` | `0`但必须子badge里的mark是有`0`位索引 | |
| active-key | 选中`badge`的索引 | `String | Number` | `0` | - |
### z-badge API
| 参数 | 说明 | 类型 | 默认值 | 必须 |
### Badge API
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| title | badge的文案标题 | `string` | `''` | `required` |
| info | 当前badge的提示消息 | `string` | `''` | |
| url | 跳转链接 | `string` | 链接直接跳转或者hash | |
| title | 内容 | `String` | `''` | - |
| info | 提示消息 | `String` | `''` | - |
| url | 跳转链接 | `String` | - | - |

View File

@ -7,6 +7,11 @@
&--bottom-action {
margin-bottom: 15px;
}
&--small,
&--normal {
margin-right: 10px;
}
}
.zan-doc-demo-block {
@ -109,8 +114,8 @@ Vue.component(Button.name, Button);
| type | 按钮类型 | `String` | `default` | `primary` `danger` |
| size | 按钮尺寸 | `String` | `normal` | `large` `small` `mini` |
| tag | 按钮标签 | `String` | `button` | 任意`HTML`标签 |
| nativeType | 按钮类型(原生) | `String` | `''` | |
| diabled | 是否禁用 | `Boolean` | `false` | |
| loading | 是否显示为加载状态 | `Boolean` | `false` | |
| block | 是否为块级元素 | `Boolean` | `false` | |
| bottomAction | 是否为底部行动按钮 | `Boolean` | `false` | |
| nativeType | 按钮类型(原生) | `String` | `''` | - |
| diabled | 是否禁用 | `Boolean` | `false` | - |
| loading | 是否显示为加载状态 | `Boolean` | `false` | - |
| block | 是否为块级元素 | `Boolean` | `false` | - |
| bottomAction | 是否为底部行动按钮 | `Boolean` | `false` | - |

View File

@ -1,3 +1,13 @@
<script>
export default {
data() {
return {
imageURL: '//img.yzcdn.cn/upload_files/2017/07/02/af5b9f44deaeb68000d7e4a711160c53.jpg'
}
}
}
</script>
## Card 图文组件
### 使用指南
@ -11,15 +21,9 @@ Vue.component(Card.name, Card);
#### 基础用法
当没有底部按钮时,右侧内容会居中显示。
:::demo 基础用法
```html
<van-card
title="商品名称是什么,两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余"
desc="描述"
thumb="https://img.yzcdn.cn/upload_files/2017/02/17/FnDwvwHmU-OiqsbjAO5X7wh1KWrR.jpg!100x100.jpg">
</van-card>
<van-card title="商品名称" desc="商品描述" :thumb="imageURL" />
```
:::
@ -29,10 +33,9 @@ Vue.component(Card.name, Card);
:::demo 高级用法
```html
<van-card
thumb="https://img.yzcdn.cn/upload_files/2017/02/17/FnDwvwHmU-OiqsbjAO5X7wh1KWrR.jpg!100x100.jpg">
<van-card :thumb="imageURL">
<div class="van-card__row" slot="title">
<h4 class="van-card__title">商品名称是什么,两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余</h4>
<h4 class="van-card__title">商品名称</h4>
<span class="van-card__price">¥ 2.00</span>
</div>
<div class="van-card__row" slot="desc">
@ -50,11 +53,10 @@ Vue.component(Card.name, Card);
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| thumb | 左侧图片 | `string` | | |
| title | 标题 | `string` | | |
| desc | 描述 | `string` | | |
| centered | 内容是否垂直居中 | `string` | `false` | |
| thumb | 左侧图片 | `String` | - | - |
| title | 标题 | `String` | - | - |
| desc | 描述 | `String` | - | - |
| centered | 内容是否垂直居中 | `String` | `false` | - |
### Slot
@ -62,6 +64,6 @@ Vue.component(Card.name, Card);
|-----------|-----------|
| title | 自定义标题 |
| desc | 自定义描述 |
| tags | 自定义tags |
| thumb | 自定义thumb |
| footer | 自定义footer |
| tags | 自定义 tags |
| thumb | 自定义 thumb |
| footer | 自定义 footer |

View File

@ -1,6 +1,6 @@
<style>
.swipe-delete-btn {
background-color: #FF4444;
.van-cell-swipe__left,
.van-cell-swipe__right {
color: #FFFFFF;
font-size: 16px;
width: 65px;
@ -9,15 +9,11 @@
text-align: center;
line-height: 44px;
}
.swipe-check-btn {
background-color: #84c483;
color: #FFFFFF;
font-size: 16px;
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;
}
</style>
## CellSwipe 滑动单元格
@ -36,22 +32,21 @@ Vue.component(CellSwipe.name, CellSwipe);
:::demo 基础用法
```html
<van-cell-swipe :right-width="65" :left-width="65">
<span slot="left">选择</span>
<van-cell-group>
<van-cell title="单元格1" value="单元格1内容"></van-cell>
</van-cell-group>
<span slot="right" class="swipe-delete-btn">删除</span>
<span slot="left" class="swipe-check-btn">选择</span>
<span slot="right">删除</span>
</van-cell-swipe>
```
:::
### API
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| left-width | 左侧滑动按钮宽度 | `number` | 0 | |
| right-width | 右侧滑动按钮宽度 | `number` | 0 | |
| left-width | 左侧滑动区域宽度 | `Number` | `0` | - |
| right-width | 右侧滑动区域宽度 | `Number` | `0` | - |
### Slot

View File

@ -8,6 +8,21 @@ export default {
};
</script>
<style>
.demo-cell {
.van-cell-text {
margin-right: 5px;
}
.van-cell__right-icon {
font-size: 16px;
}
.van-cell-text,
.van-tag--danger {
vertical-align: middle;
}
}
</style>
## Cell 单元格
### 使用指南
@ -22,86 +37,66 @@ Vue.component(CellGroup.name, CellGroup);
#### 基础用法
你可以`van-cell-group`组件看成一个容器即可
`van-cell-group`组件看成一个容器即可
:::demo 基础用法
```html
<van-cell-group>
<van-cell title="单元格1" value="单元格1内容"></van-cell>
<van-cell title="单元格2" value="单元格2内容"></van-cell>
<van-cell title="单元格2" value="单元格2内容" label="描述信息"></van-cell>
</van-cell-group>
```
:::
#### 只设置value
只设置`value`时会向左对齐。
只设置`value`时会向左对齐
:::demo 只设置value
```html
<van-cell-group>
<van-cell value="单元格1内容"></van-cell>
<van-cell value="单元格2内容"></van-cell>
<van-cell value="单元格内容"></van-cell>
</van-cell-group>
```
:::
#### 标题带描述信息
传入`label`属性,属性值为描述信息的值。
:::demo 标题带描述信息
#### 展示图标
通过`icon`属性在标题左侧展示图标
:::demo 展示图标
```html
<van-cell-group>
<van-cell title="单元格1" label="描述信息" value="查看专栏" is-link url="javascript:void(0)" @click="handleClick"></van-cell>
<van-cell title="单元格2" label="描述信息" value="查看专栏" is-link></van-cell>
<van-cell title="单元格" icon="location"></van-cell>
</van-cell-group>
```
:::
#### 带图标
#### 展示箭头
传入`isLink`属性则会在右侧显示箭头
传入`icon`属性。
:::demo 带图标
:::demo 展示箭头
```html
<van-cell-group>
<van-cell title="起码运动馆" icon="home"></van-cell>
<van-cell title="线下门店" icon="location"></van-cell>
</van-cell-group>
```
:::
#### 可点击的链接
传入`url`属性,传入`isLink`属性则会在右侧显示箭头。
:::demo 可点击的链接
```html
<van-cell-group>
<van-cell title="起码运动馆" value="进入店铺" icon="home" url="http://youzan.com" is-link></van-cell>
<van-cell title="线下门店" icon="location" url="http://youzan.com" is-link></van-cell>
<van-cell title="单元格1" is-link></van-cell>
<van-cell title="单元格2" is-link value="内容"></van-cell>
</van-cell-group>
```
:::
#### 高级用法
如以上用法不能满足你的需求,可以使用对应的`slot`来自定义显示的内容。包含三个`slot`,默认`slot``icon``title``right-icon``slot`
如以上用法不能满足你的需求,可以使用对应的`slot`来自定义显示的内容
:::demo 高级用法
```html
<van-cell-group>
<van-cell value="进入店铺" icon="home" url="http://youzan.com" is-link>
<van-cell value="进入店铺" icon="home" is-link>
<template slot="title">
<span class="van-cell-text">起码运动馆</span>
<van-tag type="danger">官方</van-tag>
</template>
</van-cell>
<van-cell title="线下门店" icon="location" url="http://youzan.com" is-link></van-cell>
<van-cell title="线下门店" icon="location" is-link></van-cell>
<van-cell title="其他">
<template slot="right-icon">
<van-icon name="passed" class="van-cell__right-icon" style="font-size: 16px;"></van-icon>
<van-icon name="search" class="van-cell__right-icon"></van-icon>
</template>
</van-cell>
</van-cell-group>
@ -112,12 +107,13 @@ Vue.component(CellGroup.name, CellGroup);
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| icon | 左侧图标 | `string` | | |
| title | 左侧标题 | `string` | | |
| value | 右侧内容 | `string` | | |
| isLink | 是否为链接,链接会在右侧出现箭头 | `boolean` | | |
| url | 跳转链接 | `string` | | |
| label | 描述信息,显示在标题下方 | `string` | | |
| icon | 左侧图标 | `String` | - | - |
| title | 左侧标题 | `String` | - | - |
| value | 右侧内容 | `String` | - | - |
| label | 标题下方的描述信息 | `String` | - | - |
| url | 跳转链接 | `String` | - | - |
| isLink | 是否展示右侧箭头 | `Boolean` | `false` | - |
| required | 是否显示表单必填符号 | `Boolean` | `false` | - |
### Slot

View File

@ -1,5 +1,56 @@
## 更新日志
## [v0.8.8](https://github.com/youzan/vant/tree/v0.8.8) (2017-09-01)
[Full Changelog](https://github.com/youzan/vant/compare/v0.8.7...v0.8.8)
**非兼容更新和新特性:**
- Checkbox: support listen to change event [\#104](https://github.com/youzan/vant/pull/104) ([chenjiahan](https://github.com/chenjiahan))
- add GoodsAction component [\#102](https://github.com/youzan/vant/pull/102) ([chenjiahan](https://github.com/chenjiahan))
- add InvalidGoods component [\#100](https://github.com/youzan/vant/pull/100) ([chenjiahan](https://github.com/chenjiahan))
- add OrderGoods component [\#99](https://github.com/youzan/vant/pull/99) ([chenjiahan](https://github.com/chenjiahan))
- add PayOrder component [\#98](https://github.com/youzan/vant/pull/98) ([chenjiahan](https://github.com/chenjiahan))
**修复:**
- 修复 make init bug [\#97](https://github.com/youzan/vant/pull/97) ([pangxie1991](https://github.com/pangxie1991))
**合并的 Pull Request (可能有不兼容改动):**
- PayOrder component add tip slot [\#105](https://github.com/youzan/vant/pull/105) ([Raistlin916](https://github.com/Raistlin916))
- Add deep-select component and fix a popup bug. [\#103](https://github.com/youzan/vant/pull/103) ([Tinysymphony](https://github.com/Tinysymphony))
- Doc: update Step/Loading/Tag/Badge documents [\#101](https://github.com/youzan/vant/pull/101) ([chenjiahan](https://github.com/chenjiahan))
## [v0.8.7](https://github.com/youzan/vant/tree/v0.8.7) (2017-08-29)
[Full Changelog](https://github.com/youzan/vant/compare/v0.8.6...v0.8.7)
**非兼容更新和新特性:**
- add ExpressWay component [\#96](https://github.com/youzan/vant/pull/96) ([chenjiahan](https://github.com/chenjiahan))
- add CellSwitch component [\#95](https://github.com/youzan/vant/pull/95) ([chenjiahan](https://github.com/chenjiahan))
- add NoticeBar && test cases [\#94](https://github.com/youzan/vant/pull/94) ([chenjiahan](https://github.com/chenjiahan))
- Dialog: support both function call and component call [\#93](https://github.com/youzan/vant/pull/93) ([chenjiahan](https://github.com/chenjiahan))
- CellSwipe: improve test coverage && code review [\#91](https://github.com/youzan/vant/pull/91) ([chenjiahan](https://github.com/chenjiahan))
- Progress: adjust DOM struct [\#90](https://github.com/youzan/vant/pull/90) ([chenjiahan](https://github.com/chenjiahan))
## [v0.8.6](https://github.com/youzan/vant/tree/v0.8.6) (2017-08-24)
[Full Changelog](https://github.com/youzan/vant/compare/v0.8.5...v0.8.6)
**非兼容更新和新特性:**
- dalete merge && class operating methods [\#88](https://github.com/youzan/vant/pull/88) ([chenjiahan](https://github.com/chenjiahan))
- directory adjust: delete entry index.js [\#87](https://github.com/youzan/vant/pull/87) ([chenjiahan](https://github.com/chenjiahan))
- Button: reduce unnecessary styles [\#86](https://github.com/youzan/vant/pull/86) ([chenjiahan](https://github.com/chenjiahan))
- Layout: optimize doc [\#85](https://github.com/youzan/vant/pull/85) ([chenjiahan](https://github.com/chenjiahan))
**修复:**
- Fix datetime-picker init value [\#89](https://github.com/youzan/vant/pull/89) ([w91](https://github.com/w91))
**处理的 Issue:**
- When 'showIndicators' set to 'false' The second image does not show [\#80](https://github.com/youzan/vant/issues/80)
## [v0.8.5](https://github.com/youzan/vant/tree/v0.8.5) (2017-08-21)
[Full Changelog](https://github.com/youzan/vant/compare/v0.8.4...v0.8.5)

View File

@ -45,8 +45,7 @@ Vue.component(Checkbox.name, Checkbox);
### 代码演示
#### 基础用法
通过`v-model`绑定值即可。当`Checkbox`选中时,绑定的值即为`true`,否则为`false`。当单个`Checkbox`使用时,更建议使用`Switch`组件。
通过`v-model`绑定 checkbox 的勾选状态
:::demo 基础用法
```html
@ -187,14 +186,20 @@ export default {
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| disabled | 是否禁用单选框 | `boolean` | `false` | |
| name | 根据这个来判断radio是否选中 | `boolean` | `false` | |
| disabled | 是否禁用单选框 | `Boolean` | `false` | - |
| name | 根据这个来判断radio是否选中 | `Boolean` | `false` | - |
### CheckboxGroup API
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| disabled | 是否禁用单选框 | `boolean` | `false` | |
| disabled | 是否禁用单选框 | `Boolean` | `false` | - |
### Checkbox Event
| 事件名称 | 说明 | 回调参数 |
|-----------|-----------|-----------|
| change | 当绑定值变化时触发的事件 | 当前组件的值 |
### CheckboxGroup Event

View File

@ -0,0 +1,169 @@
<script>
export default {
data() {
return {
items: [{
text: '所有城市',
children: [{
text: '杭州',
id: 1001
}, {
text: '温州',
id: 1002
}, {
text: '海南',
id: 1100
}, {
text: '宁波',
id: 1003
}, {
text: '义乌',
id: 1004
}, {
text: '无锡',
id: 1011
}, {
text: '常州',
id: 1012
}, {
text: '大连',
id: 1031
}, {
text: '诸暨',
id: 1005
}]
}, {
text: '浙江',
children: [{
text: '杭州',
id: 1001
}, {
text: '温州',
id: 1002
}, {
text: '宁波',
id: 1003
}, {
text: '义乌',
id: 1004
}]
}, {
text: '江苏',
children: [{
text: '无锡',
id: 1011
}, {
text: '常州',
id: 1012
}]
}],
mainActiveIndex: 0,
activeId: 1001
};
},
methods: {
onNavClick(index) {
this.mainActiveIndex = index;
},
onItemClick(data) {
console.log(data);
this.activeId = data.id;
}
}
}
</script>
## DeepSelect 分类选择组件
### 使用指南
``` javascript
import { DeepSelect } from 'vant';
Vue.component(DeepSelect.name, DeepSelect);
```
### 代码演示
#### 基础用法
:::demo 基础用法
```html
<van-deep-select
:items="items"
:main-active-index="mainActiveIndex"
:active-id="activeId"
@navclick="onNavClick"
@itemclick="onItemClick"
></van-deep-select>
```
```javascript
export default {
data() {
return {
items: items,
// 左侧高亮元素的index
mainActiveIndex: 0,
// 被选中元素的id
activeId: 1001
};
},
methods: {
onNavClick(index) {
this.mainActiveIndex = index;
},
onItemClick(data) {
console.log(data);
this.activeId = data.id;
}
}
}
</script>
```
:::
### API
#### 传入参数
| 参数 | 说明 | 类型 | 默认值 | 必须 |
|-----------|-----------|-----------|-------------|-------------|
| items | 分类显示所需的数据,具体数据结构可看 数据结构 | Array | [] | |
| mainActiveIndex | 左侧导航高亮的索引 | Number | 0 | |
| activeId | 右侧选择项高亮的数据id | Number | 0 | |
#### 事件
| 事件名 | 说明 | 参数 |
|-----------|-----------|-----------|
| navclick | 左侧导航点击时,触发的事件 | index被点击的导航的索引 |
| itemclick | 右侧选择项被点击时,会触发的事件 | data: 该点击项的数据 |
### 数据格式
#### items 分类显示所需数据的数据结构
`items` 整体为一个数组,数组内包含一系列描述分类的 object。
每个分类里text表示当前分类的名称。children 表示分类里的可选项为数组结构id被用来唯一标识每个选项
```javascript
[
{
// 导航名称
text: '所有城市',
// 该导航下所有的可选项
children: [
{
// 可选项的名称
text: '温州',
// 可选项的id高亮的时候是根据id是否和选中的id是否相同进行判断的
id: 1002
},
{
// 可选项的名称
text: '杭州',
// 可选项的id高亮的时候是根据id是否和选中的id是否相同进行判断的
id: 1001
}
]
}
]
```

View File

@ -0,0 +1,124 @@
## ExpressWay 配送方式
<script>
import { Toast, CellGroup } from 'packages/index';
export default {
data() {
return {
currentExpressType: 1,
expressList: [{
'postage': 10050,
'postage_desc': '由商家门店提供配送服务, 起送价 0.01 元',
'postage_title': '同城配送',
'express_type': 1
}, {
'postage': 0,
'postage_desc': '由商家选择合作快递为您服务',
'postage_title': '快递发货',
'express_type': 2,
'postage_warn_desc': '3天后发货'
}]
};
},
methods: {
onChange(item, index) {
Toast('配送方式更换为:' + item.postage_title);
}
},
components: {
[CellGroup.name]: CellGroup
}
}
</script>
### 使用指南
``` javascript
import { ExpressWay } from 'vant';
Vue.component(ExpressWay.name, ExpressWay);
```
### 代码演示
#### 基础用法
:::demo 基础用法
```html
<template>
<van-cell-group>
<van-express-way
v-model="currentExpressType"
:express-list="expressList"
@change="onChange"
/>
</van-cell-group>
</tempalte>
<script>
export default {
data() {
return {
currentExpressType: 1,
expressList: [{
'postage': 10050,
'postage_desc': '由商家门店提供配送服务, 起送价 0.01 元',
'postage_title': '同城配送',
'express_type': 1
}]
};
},
methods: {
onChange(item) {
Toast(`配送方式更换为:${item.postage_title}`);
}
}
}
</script>
```
:::
#### 不可修改配送方式
:::demo 不可修改配送方式
```html
<van-cell-group>
<van-express-way
:value="1"
:express-list="expressList"
:editable="false"
@change="onChange"
/>
</van-cell-group>
```
:::
### API
| 参数 | 说明 | 类型 | 默认值 | 必须 |
|-----------|-----------|-----------|-------------|-------------|
| v-model | 当前选择的配送类型 | `Number` | | 是 |
| expressList | 配送方式列表数据 | `Array` | | 是 |
| cellTitle | Cell 标题 | `String` | `配送方式` | 否 |
| actionsheetTitle | Actionsheet 标题 | `String` | `配送方式` | 否 |
| editable | 能否修改配送方式 | `Boolean` | `true` | 否 |
### 数据格式
#### expressList中的配送方式字段说明
| key | 说明 | 类型 |
|-----------|-----------|-----------|
| postage | 运费,以分为单位 | Number |
| postage_title | 配送方式 | String |
| postage_desc | 描述信息 | String |
| express_type | 配送类型 | Number |
| postage_warn_desc | 提示信息 | String |
### Event
| 事件名 | 说明 | 参数 |
|-----------|-----------|-----------|
| change | 修改配送方式时触发 | item: 对应的数据, index对应的索引 |

View File

@ -133,19 +133,19 @@ Vue.component(Field.name, Field);
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| type | 输入框类型 | `string` | `text` | `text`, `number`, `email`, `url`, `tel`, `date`, `datetime`, `password`, `textarea` |
| placeholder | 输入框placeholder | `string` | | |
| value | 输入框的值 | `string` | | |
| label | 输入框标签 | `string` | | |
| disabled | 是否禁用输入框 | `boolean` | `false` | |
| error | 输入框是否有错误 | `boolean` | `false` | |
| readonly | 输入框是否只读 | `boolean` | `false` | |
| maxlength | 输入框maxlength | `string`, `number` | | |
| rows | textarea rows | `string`, `number` | | |
| cols | textarea cols | `string`, `number` | | |
| autosize | 自动调整高度(仅支持textarea) | `boolean` | `false` | `true`, `false` |
| icon | 输入框尾部图标 | `string` | | icon中支持的类型 |
| onIconClick | 点击图标的回调函数 | `function` | | |
| type | 输入框类型 | `String` | `text` | `text`, `number`, `email`, `url`, `tel`, `date`, `datetime`, `password`, `textarea` |
| placeholder | 输入框placeholder | `String` | | |
| value | 输入框的值 | `String` | | |
| label | 输入框标签 | `String` | | |
| disabled | 是否禁用输入框 | `Boolean` | `false` | |
| error | 输入框是否有错误 | `Boolean` | `false` | |
| readonly | 输入框是否只读 | `Boolean` | `false` | |
| maxlength | 输入框maxlength | `String`, `Number` | | |
| rows | textarea rows | `String`, `Number` | | |
| cols | textarea cols | `String`, `Number` | | |
| autosize | 自动调整高度(仅支持textarea) | `Boolean` | `false` | `true`, `false` |
| icon | 输入框尾部图标 | `String` | | icon中支持的类型 |
| onIconClick | 点击图标的回调函数 | `Function` | | |
### Slot

View File

@ -0,0 +1,88 @@
<script>
import { Toast } from 'packages';
export default {
methods: {
onClickMiniBtn() {
Toast('点击图标');
},
onClickBigBtn() {
Toast('点击按钮');
}
}
}
</script>
<style>
.demo-goods-action {
.van-goods-action {
position: relative;
}
}
</style>
## GoodsAction 商品操作组件
### 使用指南
``` javascript
import {
GoodsAction,
GoodsActionBigBtn,
GoodsActionMiniBtn
} from 'vant';
Vue.component(GoodsAction.name, GoodsAction);
Vue.component(GoodsActionBigBtn.name, GoodsActionBigBtn);
Vue.component(GoodsActionMiniBtn.name, GoodsActionMiniBtn);
```
### 代码演示
:::demo
```html
<van-goods-action>
<van-goods-action-mini-btn icon="chat" @click="onClickMiniBtn">
客服
</van-goods-action-mini-btn>
<van-goods-action-mini-btn icon="cart" @click="onClickMiniBtn">
购物车
</van-goods-action-mini-btn>
<van-goods-action-big-btn @click="onClickBigBtn">
加入购物车
</van-goods-action-big-btn>
<van-goods-action-big-btn @click="onClickBigBtn" primary>
立即购买
</van-goods-action-big-btn>
</van-goods-action>
```
```javascript
export default {
methods: {
onClickMiniBtn() {
Toast('点击图标');
},
onClickBigBtn() {
Toast('点击按钮');
}
}
}
```
:::
### API
#### GoodsActionMiniBtn
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| icon | 图标 | `String` | - | Icon 组件支持的所有图标 |
| iconClass | 图标额外类名 | `String` | `''` | - |
| url | 跳转链接 | `String` | `javascript:;` | - |
#### GoodsActionBigBtn
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| url | 跳转链接 | `String` | `javascript:;` | - |
| primary | 是否主行动按钮,主行动按钮默认为红色 | `Boolean` | `false` | - |

View File

@ -8,15 +8,20 @@
.van-col {
text-align: center;
height: 120px;
height: 100px;
float: none;
display: inline-block;
.van-icon {
display: block;
}
}
.van-icon {
font-size: 45px;
display: none;
font-size: 32px;
margin: 15px 0;
display: block;
color: rgba(69, 90, 100, .8);
}
span {
@ -27,21 +32,116 @@
<script>
import Vue from 'vue';
import { Icon } from 'packages';
import { Icon, Col } from 'packages';
Vue.component('van-icon-inner', Icon);
Vue.component('van-icon', {
props: ['name'],
const icons = [
'close',
'location',
'clock',
'gold-coin',
'chat',
'exchange',
'upgrade',
'edit',
'contact',
'passed',
'points',
'delete',
'records',
'logistics',
'check',
'checked',
'gift',
'like-o',
'like',
'qr',
'qr-invalid',
'shop',
'photograph',
'add',
'add2',
'photo',
'cart',
'arrow',
'search',
'clear',
'success',
'fail',
'wechat',
'alipay',
'password-view',
'wap-nav',
'password-not-view',
'wap-home',
'ecard-pay',
'balance-pay',
'peer-pay',
'credit-pay',
'debit-pay',
'other-pay',
'cart',
'browsing-history',
'goods-collect',
'shop-collect',
'receive-gift',
'send-gift',
'setting',
'coupon',
'free-postage',
'discount',
'birthday-privilege',
'member-day-privilege',
'balance-details',
'cash-back-record',
'points-mall',
'exchange-record',
'pending-payment',
'pending-orders',
'pending-deliver',
'pending-evaluate',
'cash-on-deliver',
'gift-card-pay',
'underway',
'point-gift',
'after-sale',
'edit-data',
'question',
'description',
'card',
'gift-card',
'coupon'
];
const IconListConstructor = Vue.extend({
components: {
[Col.name]: Col,
[Icon.name]: Icon
},
render(h) {
return <van-col span="8">
<van-icon-inner name={this.name}></van-icon-inner>
<span>{this.name}</span>
</van-col>
return (
<div>
{icons.map(icon => (
<van-col span="8">
<van-icon name={icon}></van-icon>
<span>{icon}</span>
</van-col>
))}
</div>
)
}
});
export default {};
export default {
mounted() {
const IconList = new IconListConstructor({
el: document.createElement('div')
});
const block = document.querySelector('.zan-doc-demo-block');
if (block) {
block.appendChild(IconList.$el);
}
}
};
</script>
## Icon 图标
@ -57,93 +157,10 @@ Vue.component(Icon.name, Icon);
#### 基础用法
设置`name`属性为对应的图标名称即可:
:::demo 基础用法
设置`name`属性为对应的图标名称即可,所有可用的图标名称见右侧列表
:::demo 图标列表
```html
<van-icon name="success"></van-icon>
```
:::
#### 图标列表
:::demo 所有Icon
```html
<van-icon name="qr-invalid"></van-icon>
<van-icon name="qr"></van-icon>
<van-icon name="exchange"></van-icon>
<van-icon name="close"></van-icon>
<van-icon name="location"></van-icon>
<van-icon name="upgrade"></van-icon>
<van-icon name="check"></van-icon>
<van-icon name="checked"></van-icon>
<van-icon name="like-o"></van-icon>
<van-icon name="like" style="color: red;"></van-icon>
<van-icon name="chat"></van-icon>
<van-icon name="shop"></van-icon>
<van-icon name="photograph"></van-icon>
<van-icon name="add"></van-icon>
<van-icon name="add2"></van-icon>
<van-icon name="photo"></van-icon>
<van-icon name="edit"></van-icon>
<van-icon name="passed"></van-icon>
<van-icon name="cart"></van-icon>
<van-icon name="arrow"></van-icon>
<van-icon name="gift"></van-icon>
<van-icon name="search"></van-icon>
<van-icon name="clear"></van-icon>
<van-icon name="success"></van-icon>
<van-icon name="fail"></van-icon>
<van-icon name="contact"></van-icon>
<van-icon name="wechat"></van-icon>
<van-icon name="alipay"></van-icon>
<van-icon name="password-view"></van-icon>
<van-icon name="wap-nav"></van-icon>
<van-icon name="password-not-view"></van-icon>
<van-icon name="wap-home"></van-icon>
<van-icon name="ecard-pay"></van-icon>
<van-icon name="balance-pay"></van-icon>
<van-icon name="peer-pay"></van-icon>
<van-icon name="credit-pay"></van-icon>
<van-icon name="debit-pay"></van-icon>
<van-icon name="other-pay"></van-icon>
<van-icon name="cart"></van-icon>
<van-icon name="browsing-history"></van-icon>
<van-icon name="goods-collect"></van-icon>
<van-icon name="shop-collect"></van-icon>
<van-icon name="receive-gift"></van-icon>
<van-icon name="send-gift"></van-icon>
<van-icon name="setting"></van-icon>
<van-icon name="points"></van-icon>
<van-icon name="coupon"></van-icon>
<van-icon name="free-postage"></van-icon>
<van-icon name="discount"></van-icon>
<van-icon name="birthday-privilege"></van-icon>
<van-icon name="member-day-privilege"></van-icon>
<van-icon name="balance-details"></van-icon>
<van-icon name="cash-back-record"></van-icon>
<van-icon name="points-mall"></van-icon>
<van-icon name="exchange-record"></van-icon>
<van-icon name="pending-payment"></van-icon>
<van-icon name="pending-orders"></van-icon>
<van-icon name="pending-deliver"></van-icon>
<van-icon name="logistics"></van-icon>
<van-icon name="pending-evaluate"></van-icon>
<van-icon name="cash-on-deliver"></van-icon>
<van-icon name="gift-card-pay"></van-icon>
<van-icon name="underway"></van-icon>
<van-icon name="point-gift"></van-icon>
<van-icon name="after-sale"></van-icon>
<van-icon name="edit-data"></van-icon>
<van-icon name="question"></van-icon>
<van-icon name="delete"></van-icon>
<van-icon name="records"></van-icon>
<van-icon name="description"></van-icon>
<van-icon name="card"></van-icon>
<van-icon name="gift-card"></van-icon>
<van-icon name="coupon"></van-icon>
<van-icon name="clock"></van-icon>
<van-icon name="gold-coin"></van-icon>
<van-icon name="success" />
```
:::
@ -151,4 +168,4 @@ Vue.component(Icon.name, Icon);
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| name | icon名称 | `string` | `''` | |
| name | icon名称 | `String` | `''` | - |

View File

@ -11,7 +11,7 @@ import { ImagePreview } from 'packages/index';
export default {
methods: {
handleImagePreview() {
showImagePreview() {
ImagePreview([
'https://img.yzcdn.cn/upload_files/2017/03/15/FkubrzN7AgGwLlTeb1E89-T_ZjBg.png',
'https://img.yzcdn.cn/upload_files/2017/03/14/FmTPs0SeyQaAOSK1rRe1sL8RcwSY.jpeg',
@ -38,22 +38,20 @@ import { ImagePreview } from 'vant';
:::demo 基础用法
```html
<van-button @click="handleImagePreview">预览图片</van-button>
<script>
import { ImagePreview } from 'packages/index';
<van-button @click="showImagePreview">预览图片</van-button>
```
```javascript
export default {
methods: {
handleImagePreview() {
showImagePreview() {
ImagePreview([
'https://img.yzcdn.cn/upload_files/2017/03/14/FmTPs0SeyQaAOSK1rRe1sL8RcwSY.jpeg',
'https://img.yzcdn.cn/upload_files/2017/03/15/FvexrWlG_WxtCE9Omo5l27n_mAG_.jpeg'
'https://img.yzcdn.cn/1.jpg',
'https://img.yzcdn.cn/2.jpg'
]);
}
}
};
</script>
```
:::

View File

@ -0,0 +1,83 @@
## InvalidGoods 不可用商品列表
<script>
const item = {
sku: [{ v: '商品SKU1' }, { v: '商品SKU2' }],
num: 2,
sku_id: 123,
title: "商品名称",
price: 12200,
unavailable_desc: '超出配送区域',
img_url: 'https://img.yzcdn.cn/upload_files/2017/06/29/FnPSAKkEeh4FnDA09oIbmnlzWQrw.png',
};
export default {
data() {
return {
goods: [item, item, item]
}
}
}
</script>
### 使用指南
``` javascript
import { InvalidGoods } from 'vant';
Vue.component(InvalidGoods.name, InvalidGoods);
```
### 代码演示
#### 基础用法
:::demo 基础用法
```html
<template>
<van-invalid-goods :goods="goods" />
<tempalte/>
<script>
const item = {
num: 2,
sku_id: 123,
price: 12200,
title: "商品名称",
img_url: 'https://img.yzcdn.cn/...',
unavailable_desc: '超出配送区域',
sku: [
{ v: '商品SKU1' },
{ v: '商品SKU2' }
]
};
export default {
data() {
return {
goods: [item, item, item]
}
}
}
</script>
```
:::
### API
| 参数 | 说明 | 类型 | 默认值 | 必须 |
|-----------|-----------|-----------|-------------|-------------|
| goods | 商品数据 | `Array` | | 是 |
| title | 标题 | `String` | `以下商品无法一起购买,点击查看原因` | 否 |
| actionsheetTitle | 弹出层标题 | `String` | `以下商品无法一起下单` | 否 |
### 数据格式
#### data中的商品字段说明
| key | 说明 | 类型 |
|-----------|-----------|-----------|
| num | 商品数量 | `Number` |
| sku_id | 商品 id | `Number` |
| price | 商品价格,以分为单位 | `Number` |
| title | 商品标题 | `String` |
| img_url | 商品图片 url | `String` |
| unavailable_desc | 不可用原因 | `String` |
| sku | 商品 sku | `Array` |

View File

@ -79,12 +79,12 @@ Layout 组件提供了`24列栅格`,通过在`Col`上添加`span`属性设置
#### Row
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| gutter | 列元素之间的间距单位为px | `String | Number` | - | |
| prefix | className 前缀 | `String` | `van` | |
| gutter | 列元素之间的间距单位为px | `String | Number` | - | - |
| prefix | className 前缀 | `String` | `van` | - |
#### Column
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| span | 列元素宽度 | `String | Number` | - | |
| offset | 列元素偏移距离 | `String | Number` | - | |
| prefix | className 前缀 | `String` | `van` | |
| span | 列元素宽度 | `String | Number` | - | - |
| offset | 列元素偏移距离 | `String | Number` | - | - |
| prefix | className 前缀 | `String` | `van` | - |

View File

@ -157,11 +157,11 @@ export default {
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| loading | 加载时的图片 | `string` | | |
| error | 错误时的图片 | `string` | | |
| preload | 预加载高度的比例 | `string` | | |
| attempt | 尝试次数 | `number` | `3` | |
| loading | 加载时的图片 | `String` | | |
| error | 错误时的图片 | `String` | | |
| preload | 预加载高度的比例 | `String` | | |
| attempt | 尝试次数 | `Number` | `3` | |
| listenEvents | 监听的事件 | `Array` | `['scroll', 'wheel', 'mousewheel', 'resize', 'animationend', 'transitionend', 'touchmove']` | |
| adapter | 适配器 | `Object` | | |
| filter | 图片url过滤 | `Object` | | |
| lazyComponent | 是否能懒加载模块 | `boolean` | `false` | |
| lazyComponent | 是否能懒加载模块 | `Boolean` | `false` | |

View File

@ -1,19 +1,8 @@
<style>
.demo-loading {
.van-loading {
margin: 0 auto;
}
.circle-loading {
margin: 20px auto;
}
.demo-loading__example--with-bg {
background-color: rgba(17, 17, 17, 0.7);
margin: 0 auto;
width: 120px;
padding: 45px 0;
border-radius: 10px;
display: inline-block;
margin: 10px 0 10px 20px;
}
}
</style>
@ -29,39 +18,21 @@ Vue.component(Loading.name, Loading);
### 代码演示
#### 渐变深色spinner
#### 单色 spinner
:::demo 渐变深色spinner
:::demo 单色 spinner
```html
<van-loading class="some-customized-class"></van-loading>
<van-loading type="circle" color="white"></van-loading>
<van-loading type="circle" color="black"></van-loading>
```
:::
#### 渐变色spinner
#### 渐变色 spinner
:::demo 渐变色spinner
:::demo 渐变色 spinner
```html
<div class="demo-loading__example demo-loading__example--with-bg">
<van-loading class="some-customized-class" :color="'white'"></van-loading>
</div>
<style>
.demo-loading__example--with-bg {
background-color: rgba(17, 17, 17, 0.7);
width: 120px;
padding: 45px 0;
border-radius: 10px;
}
</style>
```
:::
#### 单色spinner
:::demo 单色spinner
```html
<van-loading class="circle-loading" :type="'circle'" :color="'white'"></van-loading>
<van-loading class="circle-loading" :type="'circle'" :color="'black'"></van-loading>
<van-loading type="gradient-circle" color="black"></van-loading>
<van-loading type="gradient-circle" color="white"></van-loading>
```
:::
@ -69,5 +40,5 @@ Vue.component(Loading.name, Loading);
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| color | `loading`颜色 | `string` | `black` | `black`, `white` |
| type | `loading`类型 | `string` | `gradient-circle` | `gradient-circle`, `circle` |
| color | 颜色 | `String` | `black` | `black` `white` |
| type | 类型 | `String` | `gradient-circle` | `gradient-circle` `circle` |

View File

@ -0,0 +1,69 @@
<style>
.demo-notice-bar {
.van-notice-bar:not(:first-of-type) {
margin-top: 15px;
}
}
</style>
## NoticeBar 通告栏
### 使用指南
``` javascript
import { NoticeBar } from 'vant';
Vue.component(NoticeBar.name, NoticeBar);
```
### 代码演示
#### 基础用法
:::demo 基础用法
```html
<van-notice-bar text="足协杯战线连续第2年上演广州德比战上赛季半决赛上恒大以两回合5-3的总比分淘汰富力。">
```
:::
#### 禁用滚动
文字内容多于一行时,可通过`scrollable`参数控制是否开启滚动
:::demo 禁用滚动
```html
<van-notice-bar :scrollable="false">
足协杯战线连续第2年上演广州德比战上赛季半决赛上恒大以两回合5-3的总比分淘汰富力。
</van-notice-bar>
```
:::
#### 通告栏模式
默认模式为空,支持`closeable``link`
:::demo 通告栏模式
```html
<!-- closeable 模式,在右侧显示关闭按钮 -->
<van-notice-bar mode="closeable">
足协杯战线连续第2年上演广州德比战上赛季半决赛上恒大以两回合5-3的总比分淘汰富力。
</van-notice-bar>
<!-- link 模式,在右侧显示链接箭头 -->
<van-notice-bar mode="link">
足协杯战线连续第2年上演广州德比战上赛季半决赛上恒大以两回合5-3的总比分淘汰富力。
</van-notice-bar>
```
:::
### API
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| mode | 通告栏模式 | String | `''` | `closeable` `link` |
| delay | 动画延迟时间,单位秒 | Number | `1` | - |
| speed | 滚动速率单位px | Number | `40` | - |
| scrollable | 是否滚动 | Boolean | `true` | - |
### Event
| 事件名 | 说明 | 参数 |
|-----------|-----------|-----------|
| click | 点击事件回调 | - |

View File

@ -0,0 +1,235 @@
## OrderGoods 下单页商品列表
<script>
const item1 = {
img_url: '//img.yzcdn.cn/upload_files/2017/07/02/af5b9f44deaeb68000d7e4a711160c53.jpg',
pay_price: 1050,
title: '商品 A',
num: '1'
};
const item2 = {
points_price: 200,
pay_price: 50,
img_url: '//img.yzcdn.cn/upload_files/2017/07/02/e89d56cd92ad8ce3b9d8e1babc3758b6.jpg',
title: '商品 B',
num: '15',
sku: [{ v: '商品SKU1' }, { v: '商品SKU2' }]
}
const item3 = {
pay_price: 50,
img_url: '//img.yzcdn.cn/upload_files/2017/07/02/e89d56cd92ad8ce3b9d8e1babc3758b6.jpg',
title: '商品 C',
num: '15',
is_presale: true,
delivery_time: '三天后发货',
show_delivery_time: true,
is_presale: true,
is_present: true,
message: {
'留言1': '留言1内容',
'留言2': 'https://img.yzcdn.cn/upload_files/2017/07/02/e89d56cd92ad8ce3b9d8e1babc3758b6.jpg'
}
};
export default {
data() {
return {
itemList1: [item1],
itemList2: [item2],
itemList3: [item3],
itemListMulti: [item1, item2, item3],
emptyItemList: [],
message1: '',
message2: '',
message3: '',
message4: ''
}
}
}
</script>
### 使用指南
``` javascript
import { OrderGoods } from 'vant';
Vue.component(OrderGoods.name, OrderGoods);
```
### 代码演示
#### 基础用法
:::demo 基础用法
```html
<template>
<van-order-goods
v-model="message1"
shop-name="起码运动馆"
:price="1050"
:item-list="itemList1"
/>
</template>
<script>
export default {
data() {
return {
message1: '',
itemList1: [{
img_url: '//img.yzcdn.cn/...',
pay_price: 1050,
title: '商品 A',
num: '1'
}]
}
}
}
</script>
```
:::
#### 积分商品
:::demo 积分商品
```html
<template>
<van-order-goods
v-model="message2"
shop-name="起码运动馆"
:item-list="itemList2"
:price="50"
:points="200"
/>
</template>
<script>
export default {
data() {
return {
message2: '',
itemList2: [{
points_price: 200,
pay_price: 50,
img_url: '//img.yzcdn.cn/...',
title: '商品 B',
num: '15',
sku: [
{ v: '商品SKU1' },
{ v: '商品SKU2' }
]
}]
}
}
}
</script>
```
:::
#### 预售商品
:::demo 预售商品
```html
<template>
<van-order-goods
v-model="message3"
shop-name="起码运动馆"
:price="1050"
:item-list="itemList3"
/>
</template>
<script>
export default {
data() {
return {
message3: '',
itemList3: [{
pay_price: 50,
img_url: '//img.yzcdn.cn/...',
title: '商品 C',
num: '15',
delivery_time: '三天后发货',
show_delivery_time: true,
is_presale: true,
is_present: true
}]
}
}
}
</script>
```
:::
#### 商品为空
:::demo 商品为空
```html
<van-order-goods shop-name="起码运动馆" :item-list="[]" />
```
:::
#### 多个商品
:::demo 多个商品
```html
<van-order-goods
v-model="message4"
shop-name="起码运动馆"
:item-list="itemListMulti"
:price="1050"
:message-editable="false"
/>
```
:::
### API
| 参数 | 说明 | 类型 | 默认值 |
|-----------|-----------|-----------|-------------|
| shop-name | 店铺名称 | `String` | |
| shop-link | 店铺链接 | `String` | |
| header-icon | 店铺名称左侧的图标类型 | `String` | `shop` |
| header-badge | 店铺名称右侧的徽章链接 | `String` | |
| item-list | 商品列表 | `Array` | `[]` |
| empty-icon | 商品列表为空时的图标 | `String` | |
| empty-message | 商品列表为空时的提示文案 | `String` | `当前没有可购买的商品,请重新选择` |
| empty-button-text | 商品列表为空时的按钮文案 | `String` | `返回重新选择` |
| v-model | 买家留言 | `String` | `''` |
| show-total-price | 是否显示价格栏 | `Boolean` | `true` |
| show-message | 是否显示留言栏 | `Boolean` | `true` |
| message-editable | 留言是否可以编辑 | `Boolean` | `true` |
| price | 合计金额(单位分) | `Number` | |
| points | 合计积分 | `Number` | |
### 数据格式
#### itemList 中的配送方式字段说明
| key | 说明 | 类型 |
|-----------|-----------|-----------|
| title | 商品名称 | `String` |
| img_url | 图片地址 | `String` |
| delivery_time | 发货时间 | `String` |
| num | 商品数量 | `Number` |
| points_price | 积分价格 | `Number` |
| pay_price单位分 | 金额 | `Number` |
| sku | 商品 sku | `Array` |
| message | 商品留言 | `Array` |
| is_presale | 是否为预售 | `Boolean` |
| is_present | 是否为赠品 | `Boolean` |
| is_period_buy | 是否为周期购 | `Boolean` |
| show_delivery_time | 是否显示发货时间 | `Boolean` |
### Event
| 事件名 | 说明 | 参数 |
|-----------|-----------|-----------|
| clickEmptyButton | 点击商品为空时的按钮时触发 | - |
### Slot
| name | 描述 |
|-----------|-----------|
| 默认 | 在商品列表和留言之间插入内容 |
| top | 在标题和商品列表之间插入内容 |
| bottom | 在合计价格下方插入内容 |

View File

@ -1,19 +1,6 @@
<style>
.demo-panel {
.van-panel-sum {
background: #fff;
text-align: right;
font-size: 14px;
color: #333;
line-height: 30px;
padding-right: 15px;
span {
color: red;
}
}
.van-panel-buttons {
.van-panel__footer {
text-align: right;
.van-button {
@ -21,7 +8,7 @@
}
}
.panel-content {
.van-panel__content {
padding: 20px;
}
}
@ -39,47 +26,24 @@ Vue.component(Panel.name, Panel);
### 代码演示
#### 基础用法
面板只是一个容器,里面可以放入自定义的内容。
面板只是一个容器,里面可以放入自定义的内容
:::demo 基础用法
```html
<van-panel title="标题" desc="标题描述" status="状态">
<div class="panel-content">
panel内容
</div>
<div>Panel内容</div>
</van-panel>
```
:::
#### 高级用法
使用`slot`自定义内容。比如在自定义内容中放入一个`van-card`
使用`slot`自定义内容
:::demo 高级用法
```html
<van-panel title="标题" desc="标题描述" status="状态">
<van-card
title="商品名称是什么,两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余"
desc="商品SKU1商品SKU2"
thumb="https://img.yzcdn.cn/upload_files/2017/02/17/FnDwvwHmU-OiqsbjAO5X7wh1KWrR.jpg!100x100.jpg">
<div class="van-card__row" slot="title">
<h4 class="van-card__title">商品名称是什么,两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余</h4>
<span class="van-card__price">¥ 2.00</span>
</div>
<div class="van-card__row" slot="desc">
<h4 class="van-card__desc">商品sku</h4>
<span class="van-card__num">x 2</span>
</div>
<div class="van-card__footer" slot="footer">
<van-button size="mini">按钮一</van-button>
<van-button size="mini">按钮二</van-button>
</div>
</van-card>
<div class="van-panel-sum">
合计:<span>¥ 1999.90</span>
</div>
<div class="van-panel-buttons" slot="footer">
<div>Panel内容</div>
<div slot="footer">
<van-button size="small">按钮一</van-button>
<van-button size="small" type="danger">按钮二</van-button>
</div>
@ -89,11 +53,11 @@ Vue.component(Panel.name, Panel);
### API
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| title | 标题 | `string` | | |
| desc | 描述 | `string` | | |
| status | 状态 | `string` | | |
| title | 标题 | `String` | - | - |
| desc | 描述 | `String` | - | - |
| status | 状态 | `String` | - | - |
### Slot
@ -101,5 +65,5 @@ Vue.component(Panel.name, Panel);
| name | 描述 |
|-----------|-----------|
| - | 自定义内容 |
| header | 自定义header |
| footer | 自定义footer |
| header | 自定义 header |
| footer | 自定义 footer |

View File

@ -0,0 +1,115 @@
## PayOrder 支付订单
<script>
import { Toast } from 'packages/index';
export default {
methods: {
onClickButton() {
Toast('点击按钮');
},
onClickEditAddress() {
Toast('修改地址');
}
}
}
</script>
<style>
.demo-pay-order {
.van-pay-order {
position: relative;
}
.van-edit-address {
color: #38F;
}
}
</style>
### 使用指南
``` javascript
import { PayOrder } from 'vant';
Vue.component(PayOrder.name, PayOrder);
```
### 代码演示
#### 基础用法
:::demo 基础用法
```html
<van-pay-order
:price="3050"
button-text="提交订单"
@submit="onClickButton"
/>
```
:::
#### 禁用状态
禁用状态下不会触发`submit`事件
:::demo 禁用状态
```html
<van-pay-order
disabled
:price="3050"
button-text="提交订单"
tip="您的收货地址不支持同城送, 我们已为您推荐快递"
@submit="onClickButton"
/>
```
:::
#### 加载状态
加载状态下不会触发`submit`事件
:::demo 加载状态
```html
<van-pay-order
loading
:price="3050"
button-text="提交订单"
@submit="onClickButton"
/>
```
:::
####
提示文案中的额外操作和说明
:::demo 提示文案中添加操作
```html
<van-pay-order
:price="3050"
button-text="提交订单"
@submit="onClickButton"
>
<span slot="tip">
您的收货地址不支持同城送, <span class="van-edit-address" @click="onClickEditAddress">修改地址 ></span>
</span>
</van-pay-order>
```
:::
### API
| 参数 | 说明 | 类型 | 默认值 | 必须 |
|-----------|-----------|-----------|-------------|-------------|
| price | 价格(单位分) | `Number` | | 是 |
| button-text | 按钮文字 | `String` | | 是 |
| button-type | 按钮类型 | `String` | `danger` | 否 |
| tip | 提示文案 | `String` | | 否 |
| disabled | 是否禁用按钮 | `Boolean` | `false` | 否 |
| loading | 是否显示加载中的按钮 | `Boolean` | `false` | 否 |
### Event
| 事件名 | 说明 | 参数 |
|-----------|-----------|-----------|
| submit | 按钮点击事件回调 | - |
### Slot
| 名称 | 说明 |
|-----------|-----------|
| tip | 提示文案中的额外操作和说明 |

View File

@ -143,8 +143,8 @@ export default {
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| visibileColumnCount | 每一列可见备选元素的个数 | `number` | `5` | |
| itemHeight | 选中元素区高度 | `number` | `44` | |
| visibileColumnCount | 每一列可见备选元素的个数 | `Number` | `5` | |
| itemHeight | 选中元素区高度 | `Number` | `44` | |
| columns | 对象数组,配置每一列显示的数据 | `Array` | | |
| showToolbar | 是否在组件顶部显示一个toolbar | `Boolean` | `true` | |
| title | 在toolbar上显示的标题文字 | `String` | | |

View File

@ -163,9 +163,9 @@ export default {
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| value | 利用`v-model`绑定当前组件是否显示 | `boolean` | `false` | `true`, `false` |
| overlay | 是否显示背景遮罩层 | `boolean` | `true` | `true`, `false` |
| lockOnScroll | 背景是否跟随滚动 | `boolean` | `false` | `true`, `false` |
| position | 弹出菜单位置 | `string` | | `top`, `bottom`, `right`, `left` |
| closeOnClickOverlay | 点击遮罩层是否关闭弹出菜单 | `boolean` | `true` | `true`, `false` |
| transition | 弹出菜单的`transition` | `string` | `popup-slide` | |
| v-model | 当前组件是否显示 | `Boolean` | `false` | - |
| overlay | 是否显示背景遮罩层 | `Boolean` | `true` | - |
| lockOnScroll | 背景是否跟随滚动 | `Boolean` | `false` | - |
| position | 弹出菜单位置 | `String` | - | `top`, `bottom`, `right`, `left` |
| closeOnClickOverlay | 点击遮罩层是否关闭弹出菜单 | `Boolean` | `true` | - |
| transition | 弹出菜单的`transition` | `String` | `popup-slide` | |

View File

@ -57,8 +57,8 @@ Vue.component(Progress.name, Progress);
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| inactive | 是否置灰 | `boolean` | `false` | |
| percentage | 进度百分比 | `number` | `false` | `0-100` |
| pivotText | 文字显示 | `string` | 百分比文字 | - |
| color | 进度条颜色 | `string` | `#38f` | hexvalue |
| textColor | 进度条文字颜色 | `string` | `#fff` | hexvalue |
| inactive | 是否置灰 | `Boolean` | `false` | |
| percentage | 进度百分比 | `Number` | `false` | `0-100` |
| pivotText | 文字显示 | `String` | 百分比文字 | - |
| color | 进度条颜色 | `String` | `#38f` | hexvalue |
| textColor | 进度条文字颜色 | `String` | `#fff` | hexvalue |

View File

@ -66,9 +66,15 @@ Vue.component(Quantity.name, Quantity);
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| min | 最小值 | `string`, `number` | `1` | |
| max | 最大值 | `string`, `number` | | |
| step | 步数 | `string`, `number` | `1` | |
| disabled | 是否被禁用了 | `boolean` | `false` | |
| defaultValue | 默认值 | `string`, `number` | `1` | |
| min | 最小值 | `String | Number` | `1` | - |
| max | 最大值 | `String | Number` | - | - |
| defaultValue | 默认值 | `String | Number` | `1` | - |
| step | 步数 | `String | Number` | `1` | - |
| disabled | 是否禁用 | `Boolean` | `false` | - |
### Event
| 事件名称 | 说明 | 回调参数 |
|-----------|-----------|-----------|
| change | 当绑定值变化时触发的事件 | 当前组件的值 |
| overlimit | 点击不可用的按钮时触发 | - |

View File

@ -134,14 +134,14 @@ export default {
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| disabled | 是否禁用单选框 | `boolean` | `false` | |
| name | 根据这个来判断radio是否选中 | `boolean` | `false` | |
| disabled | 是否禁用单选框 | `Boolean` | `false` | |
| name | 根据这个来判断radio是否选中 | `Boolean` | `false` | |
### RadioGroup API
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| disabled | 是否禁用单选框 | `boolean` | `false` | |
| disabled | 是否禁用单选框 | `Boolean` | `false` | |
### RadioGroup Event

View File

@ -83,8 +83,8 @@ export default {
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| placeholder | `input``placeholder`文案 | `string` | | |
| type | 搜索样式类型 | `string` | `normal` | `normal`:普通样式,`showcase`:微杂志页样式 |
| placeholder | `input``placeholder`文案 | `String` | | |
| type | 搜索样式类型 | `String` | `normal` | `normal`:普通样式,`showcase`:微杂志页样式 |
### Event

View File

@ -1,12 +1,17 @@
<style>
.demo-steps {
.steps-success {
.steps-success,
.van-icon-location {
color: #06bf04;
}
.van-button {
margin: 15px 0 0 15px;
}
.van-steps__message + p {
margin-bottom: 10px;
}
}
</style>
@ -20,7 +25,7 @@ export default {
methods: {
nextStep() {
if (++this.active > 3) this.active = 0;
this.active = ++this.active % 4;
}
}
}
@ -42,7 +47,7 @@ Vue.component(Steps.name, Steps);
:::demo 基础用法
```html
<van-steps :active="active" icon="logistics" icon-class="steps-success" title="等待商家发货" description="等待商家发货等待商家发货等待商家发货等待商家发货等待商家发货">
<van-steps :active="active">
<van-step>买家下单</van-step>
<van-step>商家接单</van-step>
<van-step>买家提货</van-step>
@ -61,7 +66,7 @@ export default {
methods: {
nextStep() {
if (++this.active > 3) this.active = 0;
this.active = ++this.active % 4;
}
}
}
@ -69,13 +74,19 @@ export default {
```
:::
#### 只显示步骤条
#### 物流描述
当你不设置`title``description`属性时,就会只显示步骤条,而没有步骤的详细信息。
通过`title``description`属性来定义物流描述信息
:::demo 只显示步骤条
:::demo 物流描述
```html
<van-steps :active="active">
<van-steps
:active="active"
icon="logistics"
icon-class="steps-success"
title="等待商家发货"
description="物流描述"
>
<van-step>买家下单</van-step>
<van-step>商家接单</van-step>
<van-step>买家提货</van-step>
@ -84,38 +95,37 @@ export default {
```
:::
#### 竖步骤条
#### 竖步骤条
可以通过设置`direction`属性来改变步骤条的显示方式,可选值有`vertical/horizontal`
可以通过设置`direction`属性来改变步骤条的显示方式
:::demo 只显示步骤条
:::demo 竖向步骤条
```html
<van-steps direction="vertical" :active="0" active-color="#f60">
<van-step>
<h3>【城市】最新的物流状态之类的表述哈哈哈哈</h3>
<p>2016-07-12 12:12:12</p>
<h3>【城市】物流状态1</h3>
<p>2016-07-12 12:40</p>
</van-step>
<van-step>
<h3>【城市】已经过了的物流状态我是折行我是折行我是折行联系电话158630099999</h3>
<p>2016-07-12 12:12:12</p>
<h3>【城市】物流状态2</h3>
<p>2016-07-11 10:00</p>
</van-step>
<van-step>
<h3>发货</h3>
<p>2016-07-12 12:12:12</p>
<h3>快件已发货</h3>
<p>2016-07-10 09:30</p>
</van-step>
</van-steps>
```
:::
### 高级用法
可以使用具名`slot`增加自定义内容,其中包含`icon``message-extra`
使用`slot`增加自定义内容
:::demo 高级用法
```html
<van-steps :active="active" title="等待商家发货">
<van-icon slot="icon" name="like"></van-icon>
<p slot="message-extra">流程</p>
<van-icon slot="icon" name="location"></van-icon>
<p slot="message-extra">物流进度</p>
<van-step>买家下单</van-step>
<van-step>商家接单</van-step>
<van-step>买家提货</van-step>
@ -128,13 +138,13 @@ export default {
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| active | 当前激活的步骤从0开始 | `number` | | |
| icon | 当前步骤的icon | `string` | | |
| iconClass | 当前步骤栏为icon添加的类 | `string` | | |
| title | 当前步骤从标题 | `string` | | |
| description | 当前步骤描述 | `string` | | |
| direction | 显示方向 | `string` | `horizontal` | `vertical/horizontal` |
| activeColor | `active`状态时的颜色 | `string` | `#06bf04` | |
| active | 当前步骤起始值为0 | `Number` | | |
| icon | 当前步骤的icon | `String` | | |
| iconClass | 当前步骤栏为icon添加的类 | `String` | | |
| title | 当前步骤从标题 | `String` | | |
| description | 当前步骤描述 | `String` | | |
| direction | 显示方向 | `String` | `horizontal` | `vertical` |
| activeColor | active状态颜色 | `String` | `#06bf04` | |
### Steps Slot
@ -142,4 +152,3 @@ export default {
|-----------|-----------|
| icon | 自定义icon区域 |
| message-extra | 状态栏添加额外的元素 |

View File

@ -135,8 +135,8 @@ export default {
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| autoPlay | 是否自动轮播 | `boolean` | `false` | `true`, `false` |
| showIndicators | 是否显示指示器 | `boolean` | `true` | `true`, `false` |
| autoPlay | 是否自动轮播 | `Boolean` | `false` | `true`, `false` |
| showIndicators | 是否显示指示器 | `Boolean` | `true` | `true`, `false` |
### 事件

View File

@ -0,0 +1,81 @@
## SwitchCell 开关单元格
`SwitchCell`组件是对`Switch``Cell`组件的封装
<script>
export default {
data() {
return {
checked: true
}
}
}
</script>
### 使用指南
``` javascript
import { SwitchCell } from 'vant';
Vue.component(SwitchCell.name, SwitchCell);
```
### 代码演示
#### 基础用法
:::demo 基础用法
```html
<template>
<van-cell-group>
<van-switch-cell v-model="checked" title="标题" />
</van-cell-group>
</template>
<script>
export default {
data() {
return {
checked: true
}
}
}
</script>
```
:::
#### 禁用状态
通过`disabled`属性可以将组件设置为禁用状态
:::demo 禁用状态
```html
<van-cell-group>
<van-switch-cell v-model="checked" :disabled="true" title="标题" />
</van-cell-group>
```
:::
#### 加载状态
通过`loading`属性可以将组件设置为加载状态
:::demo 加载状态
```html
<van-cell-group>
<van-switch-cell v-model="checked" :loading="true" title="标题" />
</van-cell-group>
```
:::
### API
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| v-model | 开关状态 | `Boolean` | | |
| title | 左侧标题 | `String` | `''` | |
| loading | 是否为加载状态 | `Boolean` | `false` | |
| disabled | 是否为禁用状态 | `Boolean` | `false` | |
### Event
| 事件名 | 说明 | 参数 |
|-----------|-----------|-----------|
| change | 开关状态切换回调 | checked: 是否选中开关 |

View File

@ -158,7 +158,7 @@ export default {
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| v-model | 开关状态 | `boolean` | `false` | `true`, `false` |
| loading | loading状态 | `boolean` | `false` | `true`, `false` |
| disabled | 禁用状态 | `boolean` | `false` | `true`, `false` |
| onChange | 开关状态切换回调(默认则改变开关状态) | `function` | - | - |
| v-model | 开关状态 | `Boolean` | `false` | `true`, `false` |
| loading | loading状态 | `Boolean` | `false` | `true`, `false` |
| disabled | 禁用状态 | `Boolean` | `false` | `true`, `false` |
| onChange | 开关状态切换回调(默认则改变开关状态) | `Function` | - | - |

View File

@ -233,18 +233,18 @@ export default {
| 参数 | 说明 | 类型 | 默认值 | 可选 |
|-----------|-----------|-----------|-------------|-------------|
| classtype | 两种UI | `string` | `line` | `line`, `card` |
| active | 默认激活的tab | `string`, `number` | `0` | |
| navclass | tabs的内部nav上的自定义classname | `string` | | |
| duration | 切换tab的动画时间 | `number` | `0.3` | | |
| classtype | 两种UI | `String` | `line` | `line`, `card` |
| active | 默认激活的tab | `String`, `Number` | `0` | |
| navclass | tabs的内部nav上的自定义classname | `String` | | |
| duration | 切换tab的动画时间 | `Number` | `0.3` | | |
### van-tab API
| 参数 | 说明 | 类型 | 默认值 | 可选 |
|-----------|-----------|-----------|-------------|-------------|
| title | tab的标题 | `string` | | |
| disabled | 是否禁用这个tab | `boolean` | `false` | |
| title | tab的标题 | `String` | | |
| disabled | 是否禁用这个tab | `Boolean` | `false` | |
### van-tabs Event

View File

@ -1,10 +1,14 @@
<style>
.tags-container {
padding: 5px 15px;
.demo-tag {
.van-tag + .van-tag {
margin-left: 10px;
}
.van-tag {
&:first-of-type {
margin-left: 15px;
}
}
}
</style>
@ -20,44 +24,37 @@ Vue.component(Tag.name, Tag);
### 代码演示
#### 基础用法
`Tag`默认是灰色,另外还有有三种类型,`danger``success``primary`,它们分别显示为红色,绿色和蓝色,你也可以加上自定义的类,为它们加上其他的颜色。
通过 type 属性控制 Tag 颜色,默认为灰色
:::demo 基础用法
```html
<div class="tags-container">
<van-tag>返现</van-tag>
</div>
<div class="tags-container">
<van-tag type="danger">返现</van-tag>
<van-tag type="success">四字标签</van-tag>
<van-tag type="primary"></van-tag>
</div>
<van-tag>标签</van-tag>
<van-tag type="danger">标签</van-tag>
<van-tag type="success">标签</van-tag>
<van-tag type="primary">标签</van-tag>
```
:::
#### 高级用法
#### 空心样式
设置`plain`属性设置为空心样式
设置`plain``true`时表示空心的`tag`,还可以设置`mark``true`,表示是否为标记。
:::demo 高级用法
:::demo 空心样式
```html
<div class="tags-container">
<van-tag>返现</van-tag>
<van-tag plain>返现</van-tag>
</div>
<div class="tags-container">
<van-tag type="danger">返现</van-tag>
<van-tag plain type="danger">返现</van-tag>
</div>
<div class="tags-container">
<van-tag type="primary">返现</van-tag>
<van-tag plain type="primary">返现</van-tag>
</div>
<div class="tags-container">
<van-tag type="success">返现</van-tag>
<van-tag plain type="success">返现</van-tag>
</div>
<van-tag plain>标签</van-tag>
<van-tag plain type="danger">标签</van-tag>
<van-tag plain type="primary">标签</van-tag>
<van-tag plain type="success">标签</van-tag>
```
:::
#### 标记样式
通过`mark`设置为标记样式
:::demo 标记样式
```html
<van-tag mark>标签</van-tag>
<van-tag mark type="danger">标签</van-tag>
<van-tag mark type="primary">标签</van-tag>
<van-tag mark type="success">标签</van-tag>
```
:::
@ -65,12 +62,12 @@ Vue.component(Tag.name, Tag);
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| plain | 是否是空心tag | `boolean` | `false` | |
| mark | 是否是标记 | `boolean` | `false` | |
| type | tag类型 | `string` | `''` | `primary`, `success`, `danger` |
| type | 类型 | `String` | `''`| `primary` `success` `danger` |
| plain | 是否为空心样式 | `Boolean` | `false` | |
| mark | 是否为标记样式 | `Boolean` | `false` | |
### Slot
| name | 描述 |
|-----------|-----------|
| - | 自定义tag显示内容 |
| - | 自定义 Tag 显示内容 |

View File

@ -52,8 +52,8 @@ export default {
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| result-type | 读取文件的方式以base64的方式读取以文本的方式读取 | `string` | `dataUrl` | `dataUrl`, `text` |
| disable | 是否禁用上传,在图片上传期间设置为true禁止用户点击此组件上传图片 | `boolean` | `false` | |
| result-type | 读取文件的方式以base64的方式读取以文本的方式读取 | `String` | `dataUrl` | `dataUrl`, `text` |
| disable | 是否禁用上传,在图片上传期间设置为true禁止用户点击此组件上传图片 | `Boolean` | `false` | |
| before-read | 读文件之前的钩子,参数为选择的文件,若返回 false 则停止读取文件。 | `Function` | | |
| after-read | 文件读完之后回调此函数,参数为{file:'选择的文件',content:'读的内容'} | `Function` | | |

View File

@ -58,7 +58,7 @@ export default {
}
},
computed: {
isWaterfallDisabled: function() {
isWaterfallDisabled() {
return this.loading || this.finished;
}
}
@ -123,8 +123,8 @@ export default {
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| v-waterfall-lower | 滚动到底部, 触发执行的函数 | `function` | - | |
| v-waterfall-upper | 滚动到顶部, 触发执行的函数 | `function` | - | |
| waterfall-disabled | 在vue对象中表示是否禁止瀑布流触发的key值 | `string` | - | |
| waterfall-offset | 触发瀑布流加载的阈值 | `number` | `300` | |
| v-waterfall-lower | 滚动到底部, 触发执行的函数 | `Function` | - | |
| v-waterfall-upper | 滚动到顶部, 触发执行的函数 | `Function` | - | |
| waterfall-disabled | 在vue对象中表示是否禁止瀑布流触发的key值 | `String` | - | |
| waterfall-offset | 触发瀑布流加载的阈值 | `Number` | `300` | |

View File

@ -54,44 +54,42 @@ export default {
</script>
<style>
a {
color: #4078c0;
text-decoration: none;
}
body {
-webkit-font-smoothing: antialiased;
}
body {
-webkit-font-smoothing: antialiased;
}
body, html {
height: 100%;
}
body, html {
height: 100%;
}
.examples-container {
height: 100%;
overflow: auto;
position: relative;
-webkit-overflow-scrolling: touch;
.examples-container {
height: 100%;
overflow: auto;
background: #f8f8f8;
position: relative;
-webkit-overflow-scrolling: touch;
&::-webkit-scrollbar {
width: 0;
}
}
.footer {
margin-top: 30px;
width: 100%;
padding: 10px 0 20px;
background: #f8f8f8;
&.footer-fixed {
position: absolute;
bottom: 0;
left: 0;
}
.footer {
margin-top: 30px;
width: 100%;
padding: 10px 0 20px;
background: #f8f8f8;
&.footer-fixed {
position: absolute;
bottom: 0;
left: 0;
}
}
.zanui-logo {
display: block;
margin: 0 auto;
width: 150px;
height: auto;
}
.zanui-logo {
display: block;
margin: 0 auto;
width: 150px;
height: auto;
}
</style>

View File

@ -7,7 +7,6 @@
</template>
<script>
import 'highlight.js/styles/color-brewer.css';
import docConfig from './doc.config';
export default {

View File

@ -6,6 +6,8 @@
<script>
export default {
name: 'demo-block',
computed: {
component() {
return this.$route.path.split('/').pop();

View File

@ -13,7 +13,7 @@
</template>
<script>
import docConfig from '../doc.config.js';
import docConfig from '../doc.config';
import MobileNav from './mobile-nav';
export default {

View File

@ -50,13 +50,17 @@ module.exports = {
"path": "/layout",
"title": "Layout 布局"
},
{
"path": "/badge",
"title": "Badge 徽章"
},
{
"path": "/button",
"title": "Button 按钮"
},
{
"path": "/icon",
"title": "Icon 图标"
"path": "/card",
"title": "Card 图文组件"
},
{
"path": "/cell",
@ -67,40 +71,52 @@ module.exports = {
"title": "CellSwipe 滑动单元格"
},
{
"path": "/progress",
"title": "Progress 进度条"
"path": "/icon",
"title": "Icon 图标"
},
{
"path": "/card",
"title": "Card 图文组件"
"path": "/image-preview",
"title": "ImagePreview 图片预览"
},
{
"path": "/panel",
"title": "Panel 面板"
"path": "/lazyload",
"title": "Lazyload 图片懒加载"
},
{
"path": "/loading",
"title": "Loading 加载"
},
{
"path": "/notice-bar",
"title": "NoticeBar 通告栏"
},
{
"path": "/panel",
"title": "Panel 面板"
},
{
"path": "/popup",
"title": "Popup 弹出菜单"
},
{
"path": "/progress",
"title": "Progress 进度条"
},
{
"path": "/quantity",
"title": "Quantity 数量选择"
},
{
"path": "/steps",
"title": "Steps 步骤条"
},
{
"path": "/tag",
"title": "Tag 标记"
},
{
"path": "/badge",
"title": "Badge 徽章"
},
{
"path": "/tab",
"title": "Tab 标签"
},
{
"path": "/popup",
"title": "Popup 弹出菜单"
"path": "/tag",
"title": "Tag 标记"
},
{
"path": "/swipe",
@ -110,21 +126,9 @@ module.exports = {
"path": "/search",
"title": "Search 搜索"
},
{
"path": "/quantity",
"title": "Quantity 数量选择"
},
{
"path": "/waterfall",
"title": "Waterfall 瀑布流"
},
{
"path": "/image-preview",
"title": "ImagePreview 图片预览"
},
{
"path": "/lazyload",
"title": "Lazyload 图片懒加载"
}
]
},
@ -132,8 +136,8 @@ module.exports = {
"groupName": "表单",
"list": [
{
"path": "/switch",
"title": "Switch 开关"
"path": "/checkbox",
"title": "Checkbox 复选框"
},
{
"path": "/field",
@ -144,8 +148,8 @@ module.exports = {
"title": "Radio 单选框"
},
{
"path": "/checkbox",
"title": "Checkbox 复选框"
"path": "/switch",
"title": "Switch 开关"
},
{
"path": "/uploader",
@ -160,14 +164,6 @@ module.exports = {
"path": "/actionsheet",
"title": "Actionsheet 行动按钮"
},
{
"path": "/toast",
"title": "Toast 轻提示"
},
{
"path": "/picker",
"title": "Picker 选择器"
},
{
"path": "/datetime-picker",
"title": "DatetimePicker 时间选择"
@ -175,6 +171,47 @@ module.exports = {
{
"path": "/dialog",
"title": "Dialog 弹出框"
},
{
"path": "/picker",
"title": "Picker 选择器"
},
{
"path": "/toast",
"title": "Toast 轻提示"
}
]
},
{
"groupName": "业务组件",
"list": [
{
"path": "/deep-select",
"title": "DeepSelect 分类选择组件"
},
{
"path": "/express-way",
"title": "ExpressWay 配送方式"
},
{
"path": "/goods-action",
"title": "GoodsAction 商品操作"
},
{
"path": "/invalid-goods",
"title": "InvalidGoods 不可用商品列表"
},
{
"path": "/order-goods",
"title": "OrderGoods 下单页商品列表"
},
{
"path": "/pay-order",
"title": "PayOrder 提交订单栏"
},
{
"path": "/switch-cell",
"title": "SwitchCell 开关单元格"
}
]
}

View File

@ -2,16 +2,15 @@ import Vue from 'vue';
import VueRouter from 'vue-router';
import App from './ExamplesApp';
import routes from './router.config';
import ZanUI from 'packages/index';
import Vant, { Lazyload } from 'packages';
import ZanDoc from 'zan-doc';
import DemoList from './components/demo-list';
import 'packages/vant-css/src/index.css';
import 'zan-doc/src/helper/touch-simulator';
import DemoList from './components/demo-list.vue';
Vue.use(ZanUI);
Vue.use(Vant);
Vue.use(ZanDoc);
Vue.use(ZanUI.Lazyload, {
Vue.use(Lazyload, {
lazyComponent: true
});
Vue.use(VueRouter);
@ -31,7 +30,7 @@ router.beforeEach((to, from, next) => {
if (container) {
document.querySelector('.examples-container').scrollTop = 0;
}
next()
next();
});
new Vue({ // eslint-disable-line

View File

@ -4,7 +4,6 @@ import App from './ExamplesDocsApp';
import routes from './router.config';
import ZanDoc from 'zan-doc';
import DemoBlock from './components/demo-block';
import 'packages/vant-css/src/index.css';
const isMobile = (function() {
var platform = navigator.userAgent.toLowerCase();
@ -14,7 +13,7 @@ const isMobile = (function() {
Vue.use(VueRouter);
Vue.use(ZanDoc);
Vue.component('demo-block', DemoBlock);
Vue.component(DemoBlock.name, DemoBlock);
const routesConfig = routes();
routesConfig.push({
@ -41,7 +40,7 @@ router.afterEach(() => {
if (!isMobile) {
window.scrollTo(0, 0);
}
})
});
new Vue({ // eslint-disable-line
render: h => h(App),

View File

@ -1,6 +1,6 @@
{
"name": "vant",
"version": "0.8.6",
"version": "0.8.9",
"description": "有赞vue wap组件库",
"main": "lib/vant.js",
"style": "lib/vant-css/index.css",
@ -42,13 +42,13 @@
"license": "ISC",
"dependencies": {
"babel-runtime": "6.x",
"vue-lazyload": "^1.0.6"
"vue-lazyload": "^1.1.2"
},
"peerDependencies": {
"vue": "2.4.2"
},
"devDependencies": {
"autoprefixer": "^7.1.2",
"autoprefixer": "^7.1.3",
"avoriaz": "2.0.0",
"babel-cli": "^6.26.0",
"babel-core": "^6.26.0",
@ -65,7 +65,7 @@
"cheerio": "^0.22.0",
"codecov": "^2.2.0",
"cross-env": "^5.0.5",
"css-loader": "^0.28.5",
"css-loader": "^0.28.7",
"eslint-plugin-vue": "^2.1.0",
"extract-text-webpack-plugin": "2.0.0",
"felint": "^0.5.0-alpha.3",
@ -81,20 +81,20 @@
"html-webpack-plugin": "^2.29.0",
"isparta-loader": "^2.0.0",
"json-templater": "^1.0.4",
"karma": "^1.7.0",
"karma": "^1.7.1",
"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.2.4",
"karma-sinon-chai": "^1.3.2",
"karma-sourcemap-loader": "^0.3.7",
"karma-spec-reporter": "^0.0.31",
"karma-webpack": "^2.0.4",
"markdown-it": "^8.3.2",
"markdown-it": "^8.4.0",
"markdown-it-container": "^2.0.0",
"mocha": "^3.4.2",
"optimize-css-assets-webpack-plugin": "^3.1.1",
"postcss": "^6.0.8",
"postcss": "^6.0.10",
"postcss-easy-import": "^2.1.0",
"postcss-loader": "^2.0.6",
"precss": "^2.0.0",
@ -117,6 +117,6 @@
"webpack": "^3.5.5",
"webpack-dev-server": "^2.7.1",
"webpack-merge": "^4.1.0",
"zan-doc": "^0.2.2"
"zan-doc": "^0.2.10"
}
}

View File

@ -1,12 +1,8 @@
<template>
<a
class="van-badge"
:class="{ 'van-badge--select': isSelect }"
:href="url"
@click="handleClick">
<a :class="['van-badge', { 'van-badge--select': isSelect }]" :href="url" @click="onClick">
<div class="van-badge__active"></div>
<div v-if="info" class="van-badge__info">{{info}}</div>
{{title}}
<div v-if="info" class="van-badge__info">{{ info }}</div>
{{ title }}
</a>
</template>
@ -40,12 +36,8 @@ export default {
},
methods: {
handleClick(e) {
this.$emit('click', e, {
title: this.title,
url: this.url,
info: this.info
});
onClick() {
this.$emit('click', this.$parent.badges.indexOf(this));
}
}
};

View File

@ -2,7 +2,7 @@
<a :class="['van-cell', { 'van-cell--required': required }]" :href="url" @click="$emit('click')">
<div
class="van-cell__title"
v-if="this.$slots.title || title"
v-if="$slots.title || title"
>
<slot name="icon">
<i v-if="icon" class="van-icon" :class="'van-icon-' + icon"></i>
@ -14,10 +14,10 @@
</div>
<div
class="van-cell__value"
v-if="value || this.$slots.default"
v-if="value || $slots.default"
:class="{
'van-cell__value--link': isLink,
'van-cell__value--alone': !this.$slots.title && !title && !label
'van-cell__value--alone': !$slots.title && !title && !label
}"
>
<slot>

View File

@ -31,22 +31,23 @@ export default {
mixins: [findParent],
props: {
disabled: Boolean,
value: {},
disabled: Boolean,
name: [String, Number]
},
watch: {
value(val) {
this.$emit('change', val);
}
},
computed: {
/**
* `checkbox`是否在`van-checkbox-group`
*/
// checkbox van-checkbox-group
isGroup() {
return !!this.findParentByComponentName('van-checkbox-group');
},
/**
* `checkbox`当前值
*/
currentValue: {
get() {
return this.isGroup && this.parentGroup ? this.parentGroup.value.indexOf(this.name) !== -1 : this.value;
@ -75,9 +76,6 @@ export default {
}
},
/**
* `checkbox`是否被选中
*/
isChecked() {
const currentValue = this.currentValue;
if ({}.toString.call(currentValue) === '[object Boolean]') {
@ -87,9 +85,6 @@ export default {
}
},
/**
* `checkbox`是否被禁用
*/
isDisabled() {
return this.isGroup && this.parentGroup
? this.parentGroup.disabled

View File

@ -0,0 +1,85 @@
<template>
<div class="van-deep-select" v-bind:style="{ height: mainHeight + 'px' }">
<div class="van-deep-select__nav">
<div
v-for="(item, index) in items"
class="van-deep-select__nitem"
v-bind:class="{ 'van-deep-select__nitem--active': mainActiveIndex === index }"
@click="onNavClick(index)">
{{ item.text }}
</div>
</div>
<div class="van-deep-select__content" v-bind:style="{ height: itemHeight + 'px' }">
<div
v-for="item in subItems"
:key="item.id"
class="van-deep-select__item"
v-bind:class="{ 'van-deep-select__item--active': activeId === item.id }"
@click="onItemSelect(item)">
{{ item.text }}
<van-icon
v-if="activeId === item.id"
name="success"
class="van-deep-select__selected"
></van-icon>
</div>
</div>
</div>
</template>
<script>
import Icon from 'packages/icon';
export default {
name: 'van-deep-select',
components: {
'van-icon': Icon
},
props: {
items: {
type: Array,
default () {
return [];
}
},
mainActiveIndex: {
type: Number,
default: 0
},
activeId: {
type: Number,
default: 0
},
maxHeight: {
type: Number,
default: 300
}
},
computed: {
subItems() {
const selectedItem = this.items[this.mainActiveIndex] || {};
return selectedItem.children || [];
},
mainHeight() {
const maxHeight = Math.max(this.items.length * 44, this.subItems.length * 44);
return Math.min(maxHeight, this.maxHeight);
},
itemHeight() {
return Math.min(this.subItems.length * 44, this.maxHeight);
}
},
methods: {
onNavClick(index) {
this.$emit('navclick', index);
},
onItemSelect(data) {
const exportData = Object.assign({}, data);
this.$emit('itemclick', exportData);
}
}
};
</script>

View File

@ -0,0 +1,32 @@
<template>
<van-cell class="van-express-way-option" @click="$emit('change')">
<van-radio :name="data.express_type" :value="currentExpressWay" />
<div class="van-express-way-option__content">
<h3 class="van-express-way-option__title">
<span>{{ data.postage_title }}</span>
<span>{{ data.postage }}</span>
</h3>
<p>{{ data.postage_desc }}</p>
<div class="van-express-way-option__warn" v-if="data.postage_warn_desc">{{ data.postage_warn_desc }}</div>
</div>
</van-cell>
</template>
<script>
import Cell from '../cell';
import Radio from '../radio';
export default {
name: 'van-express-way-option',
components: {
[Cell.name]: Cell,
[Radio.name]: Radio
},
props: {
data: Object,
currentExpressWay: Number
}
};
</script>

View File

@ -0,0 +1,100 @@
<template>
<van-cell class="van-express-way">
<van-actionsheet v-if="computedEditable" v-model="showActionsheet" :title="actionsheetTitle" >
<van-cell-group>
<van-express-way-option
v-for="(item, index) in computedList"
:key="item.express_type"
:data="item"
:currentExpressWay="value"
@change="onSelectExpressWay(item, index)"
/>
</van-cell-group>
</van-actionsheet>
<van-cell :title="cellTitle" :isLink="computedEditable" @click="showActionsheet = computedEditable">
<p class="van-express-way__fee">{{ currentOption.postage }}</p>
<p class="van-express-way__type">{{ currentOption.postage_title }}</p>
</van-cell>
</van-cell>
</template>
<script>
import Option from './Option';
import Cell from '../cell';
import CellGroup from '../cell-group';
import Actionsheet from '../actionsheet';
export default {
name: 'van-express-way',
components: {
[Option.name]: Option,
[Cell.name]: Cell,
[CellGroup.name]: CellGroup,
[Actionsheet.name]: Actionsheet
},
props: {
value: {
type: Number,
required: true
},
expressList: {
type: Array,
required: true
},
cellTitle: {
type: String,
default: '配送方式'
},
actionsheetTitle: {
type: String,
default: '配送方式'
},
editable: {
type: Boolean,
default: true
}
},
data() {
return {
showActionsheet: false
};
},
computed: {
computedList() {
return this.expressList.map(item => ({
...item,
postage: this.calcPostage(item.postage)
}));
},
computedEditable() {
return this.expressList && this.expressList.length >= 2 && this.editable;
},
currentOption() {
for (let i = 0; i < this.computedList.length; i++) {
if (this.computedList[i].express_type === this.value) {
return this.computedList[i];
}
}
return {};
}
},
methods: {
onSelectExpressWay(item, index) {
this.showActionsheet = false;
this.$emit('input', item.express_type);
this.$emit('change', item, index);
},
calcPostage(postage) {
return postage === 0 ? '免运费' : '¥' + (postage / 100).toFixed(2);
}
}
};
</script>

View File

@ -47,10 +47,11 @@
</template>
<script>
const VALID_TYPES = ['text', 'number', 'email', 'url', 'tel', 'date', 'time', 'datetime', 'password', 'textarea'];
import Cell from '../cell';
import Icon from '../icon';
const VALID_TYPES = ['text', 'number', 'email', 'url', 'tel', 'date', 'time', 'datetime', 'password', 'textarea'];
export default {
name: 'van-field',
@ -63,15 +64,14 @@ export default {
type: {
type: String,
default: 'text',
validator(value) {
return VALID_TYPES.indexOf(value) > -1;
}
validator: value => VALID_TYPES.indexOf(value) > -1
},
placeholder: String,
value: {},
icon: String,
label: String,
disabled: Boolean,
placeholder: String,
error: Boolean,
disabled: Boolean,
readonly: Boolean,
required: Boolean,
maxlength: [String, Number],
@ -82,7 +82,6 @@ export default {
type: Boolean,
default: false
},
icon: String,
onIconClick: {
type: Function,
default: () => {}

View File

@ -0,0 +1,32 @@
<template>
<van-button
tag="a"
:href="url"
class="van-goods-action__big-btn"
:type="primary ? 'primary' : 'default'"
@click="$emit('click', $event)"
bottomAction
>
<slot></slot>
</van-button>
</template>
<script>
import Button from '../button';
export default {
name: 'van-goods-action-big-btn',
components: {
[Button.name]: Button
},
props: {
primary: Boolean,
url: {
type: String,
default: 'javascript:;'
}
}
};
</script>

View File

@ -0,0 +1,30 @@
<template>
<a :href="url" class="van-goods-action__mini-btn" @click="$emit('click', $event);">
<van-icon :class="['van-goods-action__mini-btn-icon', iconClass]" :name="icon" />
<slot></slot>
</a>
</template>
<script>
import Icon from '../icon';
export default {
name: 'van-goods-action-mini-btn',
components: {
[Icon.name]: Icon
},
props: {
icon: String,
iconClass: {
type: String,
default: ''
},
url: {
type: String,
default: 'javascript:;'
}
}
};
</script>

View File

@ -0,0 +1,11 @@
<template>
<div class="van-goods-action">
<slot></slot>
</div>
</template>
<script>
export default {
name: 'van-goods-action'
};
</script>

View File

@ -1,77 +1,97 @@
import Actionsheet from './actionsheet';
import Badge from './badge';
import BadgeGroup from './badge-group';
import Button from './button';
import Switch from './switch';
import Field from './field';
import Radio from './radio';
import Card from './card';
import Cell from './cell';
import Icon from './icon';
import CellGroup from './cell-group';
import CellSwipe from './cell-swipe';
import Popup from './popup';
import Dialog from './dialog';
import Picker from './picker';
import RadioGroup from './radio-group';
import Waterfall from './waterfall';
import Loading from './loading';
import Panel from './panel';
import Card from './card';
import Steps from './steps';
import Tag from './tag';
import Checkbox from './checkbox';
import CheckboxGroup from './checkbox-group';
import BadgeGroup from './badge-group';
import Badge from './badge';
import Col from './col';
import DatetimePicker from './datetime-picker';
import DeepSelect from './deep-select';
import Dialog from './dialog';
import ExpressWay from './express-way';
import Field from './field';
import GoodsAction from './goods-action';
import GoodsActionBigBtn from './goods-action-big-btn';
import GoodsActionMiniBtn from './goods-action-mini-btn';
import Icon from './icon';
import ImagePreview from './image-preview';
import InvalidGoods from './invalid-goods';
import Lazyload from './lazyload';
import Loading from './loading';
import NoticeBar from './notice-bar';
import OrderGoods from './order-goods';
import Panel from './panel';
import PayOrder from './pay-order';
import Picker from './picker';
import Popup from './popup';
import Progress from './progress';
import Quantity from './quantity';
import Radio from './radio';
import RadioGroup from './radio-group';
import Row from './row';
import Search from './search';
import Step from './step';
import Tabs from './tabs';
import Tab from './tab';
import Lazyload from './lazyload';
import ImagePreview from './image-preview';
import Col from './col';
import Row from './row';
import Actionsheet from './actionsheet';
import Quantity from './quantity';
import Progress from './progress';
import Toast from './toast';
import Uploader from './uploader';
import Steps from './steps';
import Swipe from './swipe';
import SwipeItem from './swipe-item';
import DatetimePicker from './datetime-picker';
import Switch from './switch';
import SwitchCell from './switch-cell';
import Tab from './tab';
import Tabs from './tabs';
import Tag from './tag';
import Toast from './toast';
import Uploader from './uploader';
import Waterfall from './waterfall';
const version = '0.8.6';
const version = '0.8.9';
const components = [
Actionsheet,
Badge,
BadgeGroup,
Button,
Switch,
Field,
Radio,
Card,
Cell,
Icon,
CellGroup,
CellSwipe,
Popup,
Picker,
RadioGroup,
Loading,
Panel,
Card,
Steps,
Tag,
Checkbox,
CheckboxGroup,
BadgeGroup,
Badge,
Col,
DatetimePicker,
DeepSelect,
ExpressWay,
Field,
GoodsAction,
GoodsActionBigBtn,
GoodsActionMiniBtn,
Icon,
InvalidGoods,
Loading,
NoticeBar,
OrderGoods,
Panel,
PayOrder,
Picker,
Popup,
Progress,
Quantity,
Radio,
RadioGroup,
Row,
Search,
Step,
Tabs,
Tab,
Col,
Row,
Actionsheet,
Quantity,
Progress,
Uploader,
Steps,
Swipe,
SwipeItem,
DatetimePicker
Switch,
SwitchCell,
Tab,
Tabs,
Tag,
Uploader
];
const install = function(Vue) {
@ -90,84 +110,56 @@ if (typeof window !== 'undefined' && window.Vue) {
export {
install,
version,
Actionsheet,
Badge,
BadgeGroup,
Button,
Switch,
Field,
Radio,
Card,
Cell,
Icon,
CellGroup,
CellSwipe,
Popup,
Dialog,
Picker,
RadioGroup,
Waterfall,
Loading,
Panel,
Card,
Steps,
Tag,
Checkbox,
CheckboxGroup,
BadgeGroup,
Badge,
Col,
DatetimePicker,
DeepSelect,
Dialog,
ExpressWay,
Field,
GoodsAction,
GoodsActionBigBtn,
GoodsActionMiniBtn,
Icon,
ImagePreview,
InvalidGoods,
Lazyload,
Loading,
NoticeBar,
OrderGoods,
Panel,
PayOrder,
Picker,
Popup,
Progress,
Quantity,
Radio,
RadioGroup,
Row,
Search,
Step,
Tabs,
Tab,
Lazyload,
ImagePreview,
Col,
Row,
Actionsheet,
Quantity,
Progress,
Toast,
Uploader,
Steps,
Swipe,
SwipeItem,
DatetimePicker
Switch,
SwitchCell,
Tab,
Tabs,
Tag,
Toast,
Uploader,
Waterfall
};
export default {
install,
version,
Button,
Switch,
Field,
Radio,
Cell,
Icon,
CellGroup,
CellSwipe,
Popup,
Dialog,
Picker,
RadioGroup,
Waterfall,
Loading,
Panel,
Card,
Steps,
Tag,
Checkbox,
CheckboxGroup,
BadgeGroup,
Badge,
Search,
Step,
Tabs,
Tab,
Lazyload,
ImagePreview,
Col,
Row,
Actionsheet,
Quantity,
Progress,
Toast,
Uploader,
Swipe,
SwipeItem,
DatetimePicker
version
};

View File

@ -0,0 +1,30 @@
<template>
<div class="van-invalid-goods-card">
<div class="van-invalid-goods__thumb">
<img :src="item.img_url" />
<div class="van-invalid-goods-card__flag">失效</div>
</div>
<div class="van-invalid-goods-card__content">
<div class="van-invalid-goods-card__row">
<h4 class="van-invalid-goods-card__title">{{ item.title }}</h4>
<span class="van-invalid-goods-card__price">¥{{ item.price }}</span>
</div>
<div class="van-invalid-goods-card__row">
<div class="van-invalid-goods-card__sku">{{ item.sku }}</div>
<span class="van-invalid-goods-card__num">x{{ item.num }}</span>
</div>
<div class="van-invalid-goods-card__desc">{{ item.unavailable_desc }}</div>
</div>
</div>
</template>
<script>
export default {
name: 'van-invalid-goods-card',
props: {
item: Object
}
};
</script>

View File

@ -0,0 +1,78 @@
<template>
<div>
<div class="van-invalid-goods" @click="showDetail = true">
<h3 class="van-invalid-goods__title">{{ title }}</h3>
<van-cell-group class="van-invalid-goods__container">
<div class="van-invalid-goods__gallery">
<div v-for="item in formattedGoods" :key="item.sku_id" class="van-invalid-goods__thumb">
<img :src="item.img_url" />
</div>
</div>
<div class="van-invalid-goods__count">
<span>{{ formattedGoods.length }}</span>
<van-icon name="arrow" />
</div>
</van-cell-group>
</div>
<van-actionsheet v-model="showDetail" :title="actionsheetTitle">
<div class="van-invalid-goods__list">
<van-invalid-goods-card v-for="item in formattedGoods" :key="item.sku_id" :item="item" />
</div>
</van-actionsheet>
</div>
</template>
<script>
import Card from './Card';
import Icon from '../icon';
import CellGroup from '../cell-group';
import Actionsheet from '../actionsheet';
export default {
name: 'van-invalid-goods',
components: {
[Card.name]: Card,
[Icon.name]: Icon,
[CellGroup.name]: CellGroup,
[Actionsheet.name]: Actionsheet
},
props: {
goods: {
type: Array,
required: true
},
title: {
type: String,
default: '以下商品无法一起购买,点击查看原因'
},
actionsheetTitle: {
type: String,
default: '以下商品无法一起下单'
}
},
data() {
return {
showDetail: false
};
},
methods: {
getSkuStr(arr) {
return arr.filter(item => item.v).map(item => item.v).join(', ');
}
},
computed: {
formattedGoods() {
return this.goods.map(item => ({
...item,
price: parseFloat(item.price / 100, 10).toFixed(2),
sku: this.getSkuStr(item.sku)
}));
}
}
};
</script>

View File

@ -99,6 +99,7 @@ export default {
* 显示popup
*/
open() {
/* istanbul ignore if */
if (this.$isServer) return;
if (this.opened) return;

View File

@ -1,12 +1,7 @@
import Vue from 'vue';
let context;
const _global = Vue.prototype.$isServer ? global : window;
if (_global && _global.popupContext) {
context = _global.popupContext;
}
const DEFAULT_CONTEXT = {
idSeed: 1,
zIndex: 2000,
@ -15,23 +10,24 @@ const DEFAULT_CONTEXT = {
modalStack: []
};
context = _global.popupContext = {
...DEFAULT_CONTEXT,
...context
};
if (!_global.popupContext) {
_global.popupContext = {
...DEFAULT_CONTEXT
};
}
const PopupContext = {
getContext(key) {
return context[key];
return _global.popupContext[key];
},
setContext(key, value) {
context[key] = value;
_global.popupContext[key] = value;
},
plusKeyByOne(key) {
const oldVal = +context[key];
context[key] = oldVal + 1;
const oldVal = +_global.popupContext[key];
_global.popupContext[key] = oldVal + 1;
return oldVal;
}

View File

@ -0,0 +1,93 @@
<template>
<div v-show="showNoticeBar" @click="$emit('click')" :class="['van-notice-bar', { 'van-notice-bar--withicon': mode }]">
<div class="van-notice-bar__content-wrap" ref="contentWrap">
<div class="van-notice-bar__content" ref="content" :style="contentStyle" @transitionend="onTransitionEnd">
<slot>{{ text }}</slot>
</div>
</div>
<van-icon class="van-notice-bar__icon" :name="iconName" v-if="iconName" @click="onClickIcon" />
</div>
</template>
<script>
import Icon from '../icon';
const NOTICE_BAR_MODE = ['', 'closeable', 'link'];
export default {
name: 'van-notice-bar',
components: {
[Icon.name]: Icon
},
props: {
text: String,
mode: {
type: String,
default: '',
validator: val => NOTICE_BAR_MODE.indexOf(val) !== -1
},
delay: {
type: [String, Number],
default: 1
},
scrollable: {
type: Boolean,
default: true
},
speed: {
type: Number,
default: 40
}
},
data() {
return {
duration: 0,
offsetWidth: 0,
showNoticeBar: true,
diableTransition: false
};
},
computed: {
iconName() {
return this.mode === 'closeable' ? 'close' : this.mode === 'link' ? 'arrow' : '';
},
contentStyle() {
return {
left: -this.offsetWidth + 'px',
transitionDelay: this.delay + 's',
transitionDuration: this.duration + 's',
transitionProperty: this.diableTransition ? 'none' : 'left'
};
}
},
mounted() {
const offsetWidth = this.$refs.content.getBoundingClientRect().width;
const wrapWidth = this.$refs.contentWrap.getBoundingClientRect().width;
if (this.scrollable && offsetWidth > wrapWidth) {
this.offsetWidth = offsetWidth;
this.duration = (offsetWidth + wrapWidth) / this.speed;
}
},
methods: {
onClickIcon() {
this.showNoticeBar = this.mode !== 'closeable';
},
onTransitionEnd() {
const { offsetWidth } = this;
this.diableTransition = true;
this.offsetWidth = 0;
setTimeout(() => {
this.diableTransition = false;
this.offsetWidth = offsetWidth;
}, 50);
}
}
};
</script>

View File

@ -0,0 +1,102 @@
<template>
<div class="van-order-goods-card">
<van-card>
<div slot="thumb">
<img :src="data.img_url" />
<span v-if="data.is_present" class="van-order-goods-card__present"></span>
</div>
<div class="van-card__row" slot="title">
<h4 class="van-card__title">{{ data.title }}</h4>
<span class="van-card__price">{{ price }}</span>
</div>
<template slot="desc">
<div class="van-card__row">
<p class="van-card__desc">{{ desc }}</p>
<span class="van-card__num">x {{ data.num }}</span>
</div>
<div class="van-card__row">
<div class="van-order-goods-card__tags">
<span v-if="data.is_presale" class="van-order-goods-card__tag-green">预售</span>
<span v-if="data.is_period_buy" class="van-order-goods-card__tag-red">周期购</span>
</div>
<van-button
class="van-order-goods-card__message-button"
v-if="hasMessage"
@click="onClickMessageButton"
>
查看留言
</van-button>
</div>
</template>
</van-card>
<van-cell class="van-order-goods-card__delivery" v-if="data.show_delivery_time" title="发货时间" :value="data.delivery_time" />
<van-popup v-if="hasMessage" class="van-order-goods-card__message" v-model="showMessage" position="right">
<h2>备注信息</h2>
<ul>
<li v-for="(value, key) in data.message">
<label>{{ key }}</label>
<a v-if="isURL(value)" :href="value">
<img :src="value" />
</a>
<p v-else>{{ value }}</p>
</li>
</ul>
<div class="van-order-goods-card__button">
<van-button size="large" @click="showMessage = false">查看订单详情</van-button>
</div>
</van-popup>
</div>
</template>
<script>
import Card from '../card';
import Cell from '../cell';
import Button from '../button';
import Popup from '../popup';
import { getTotalPrice } from './utils';
export default {
name: 'van-order-goods-card',
components: {
[Card.name]: Card,
[Cell.name]: Cell,
[Popup.name]: Popup,
[Button.name]: Button
},
props: {
data: {
type: Object,
required: true
}
},
data() {
return {
showMessage: false
};
},
computed: {
price() {
return getTotalPrice(this.data.pay_price, this.data.points_price);
},
desc() {
return this.data.sku ? this.data.sku.filter(item => item.v).map(item => item.v).join(', ') : '';
},
hasMessage() {
return this.data.message && Object.keys(this.data.message).length;
}
},
methods: {
onClickMessageButton() {
this.showMessage = true;
},
isURL(value) {
return /^\s*http(s)*:\/\/.+/.test(value);
}
}
};
</script>

View File

@ -0,0 +1,25 @@
<template>
<div class="van-order-goods-empty">
<img :src="icon" />
<p>{{ message }}</p>
<van-button @click="$emit('clickEmptyButton')">{{ buttonText }}</van-button>
</div>
</template>
<script>
import Button from '../button';
export default {
name: 'van-order-goods-empty',
components: {
[Button.name]: Button
},
props: {
icon: String,
message: String,
buttonText: String
}
};
</script>

View File

@ -0,0 +1,26 @@
<template>
<div class="van-order-goods-header">
<van-icon :name="icon" />
<a :href="link">{{ title }}</a>
<img v-if="badge" :src="badge" />
</div>
</template>
<script>
import Icon from '../icon';
export default {
name: 'van-order-goods-header',
components: {
[Icon.name]: Icon
},
props: {
title: String,
icon: String,
link: String,
badge: String
}
};
</script>

View File

@ -0,0 +1,50 @@
<template>
<van-cell class="van-order-goods-message" title="买家留言:">
<textarea
v-if="editable"
:value="message"
:class="{ 'van-order-goods-message-focused': textareaFocused }"
placeholder="点击给商家留言"
@focus="textareaFocused = true"
@blur="textareaFocused = false"
@input="onChange"
/>
<p v-else>{{ message }}</p>
</van-cell>
</template>
<script>
import Cell from '../cell';
export default {
name: 'van-order-goods-message',
components: {
[Cell.name]: Cell
},
props: {
message: String,
editable: Boolean
},
data() {
return {
textareaFocused: false
};
},
methods: {
onChange(event) {
this.$emit('change', event.target.value);
}
},
created() {
// ""
if (!this.editable && !this.message) {
this.$emit('change', '无');
}
}
};
</script>

View File

@ -0,0 +1,32 @@
<template>
<van-cell
class="van-order-goods-price"
title="合计"
:value="totalPrice"
/>
</template>
<script>
import Cell from '../cell';
import { getTotalPrice } from './utils';
export default {
name: 'van-order-goods-price',
components: {
[Cell.name]: Cell
},
props: {
price: Number,
points: Number,
isPoints: Boolean
},
computed: {
totalPrice() {
return getTotalPrice(this.price, this.points, this.isPoints);
}
}
};
</script>

View File

@ -0,0 +1,114 @@
<template>
<van-cell-group class="van-order-goods">
<van-order-goods-header
:title="shopName"
:link="shopLink"
:icon="headerIcon"
:badge="headerBadge"
/>
<slot name="top"></slot>
<van-order-goods-empty
v-if="isEmpty"
:icon="emptyIcon"
:message="emptyMessage"
:button-text="emptyButtonText"
@clickEmptyButton="$emit('clickEmptyButton')"
/>
<div class="van-order-goods-list">
<van-order-goods-card
v-for="item in itemList"
:data="item"
:express-way="expressWay"
:key="item.title + item.img_url"
/>
</div>
<slot></slot>
<template v-if="!isEmpty">
<van-order-goods-message v-if="showMessage" :message="message" :editable="messageEditable" @change="onMessageChange" />
<van-order-goods-price v-if="showTotalPrice" :price="price" :points="points" />
</template>
<slot name="bottom"></slot>
</van-cell-group>
</template>
<script>
import Header from './Header';
import Empty from './Empty';
import Message from './Message';
import Price from './Price';
import Card from './Card';
import CellGroup from '../cell-group';
export default {
name: 'van-order-goods',
components: {
[Empty.name]: Empty,
[Header.name]: Header,
[Message.name]: Message,
[Price.name]: Price,
[Card.name]: Card,
[CellGroup.name]: CellGroup
},
model: {
prop: 'message'
},
props: {
shopName: String,
shopLink: String,
message: String,
price: Number,
points: Number,
expressWay: String,
headerBadge: String,
headerIcon: {
type: String,
default: 'shop'
},
emptyIcon: {
type: String,
default: '//b.yzcdn.cn/v2/image/wap/trade/new_order/empty@2x.png'
},
emptyMessage: {
type: String,
default: '当前没有可购买的商品,请重新选择'
},
emptyButtonText: {
type: String,
default: '返回重新选择'
},
showMessage: {
type: Boolean,
default: true
},
showTotalPrice: {
type: Boolean,
default: true
},
messageEditable: {
type: Boolean,
default: true
},
itemList: {
type: Array,
default() {
return [];
}
}
},
computed: {
isEmpty() {
return this.itemList.length === 0;
}
},
methods: {
onMessageChange(message) {
this.$emit('input', message);
}
}
};
</script>

View File

@ -0,0 +1,13 @@
/**
* 拼接商品价格金额和积分
*/
export function getTotalPrice(price, points) {
const arr = [];
if (points) {
arr.push(points + '积分');
}
if (price) {
arr.push('¥' + (price / 100).toFixed(2));
}
return arr.join(' + ');
}

View File

@ -10,7 +10,7 @@
<div class="van-panel__content">
<slot></slot>
</div>
<div class="van-panel__footer" v-if="this.$slots.footer">
<div class="van-panel__footer" v-if="$slots.footer">
<slot name="footer"></slot>
</div>
</div>

View File

@ -0,0 +1,66 @@
<template>
<div class="van-pay-order">
<div class="van-pay-order__tip" v-show="tip || hasTipSlot">{{ tip }}<slot name="tip" /></div>
<div class="van-pay-order__bar">
<div class="van-pay-order__price">
<template v-if="hasPrice">
<span class="van-pay-order__price-text">合计</span>
<span class="van-pay-order__price-interger">¥{{ priceInterger }}.</span>
<span class="van-pay-order__price-decimal">{{ priceDecimal }}</span>
</template>
</div>
<van-button :type="buttonType" :disabled="disabled" :loading="loading" @click="onSubmit">
{{ loading ? '' : buttonText }}
</van-button>
</div>
</div>
</template>
<script>
import Button from '../button';
export default {
name: 'van-pay-order',
components: {
[Button.name]: Button
},
props: {
tip: String,
type: Number,
price: Number,
loading: Boolean,
disabled: Boolean,
buttonText: String,
buttonType: {
type: String,
default: 'danger'
}
},
computed: {
hasPrice() {
return typeof this.price === 'number';
},
priceInterger() {
return Math.floor(this.price / 100);
},
priceDecimal() {
const decimal = this.price % 100;
return (decimal < 10 ? '0' : '') + decimal;
},
hasTipSlot () {
return !!this.$slots['tip']
}
},
methods: {
onSubmit() {
if (!this.disabled && !this.loading) {
this.$emit('submit');
}
}
}
};
</script>

View File

@ -3,7 +3,10 @@
<div class="van-swipe__items">
<slot></slot>
</div>
<div class="van-swipe__indicators" v-if="showIndicators">
<div
class="van-swipe__indicators"
v-if="showIndicators && swipes.length > 1"
>
<span class="van-swipe__indicator" v-for="(item, index) in swipes.length" :key="index" :class="{
'van-swipe__indicator--active': currIndex === index
}">

View File

@ -0,0 +1,32 @@
<template>
<van-cell :title="title" class="van-switch-cell">
<van-switch :value="value" @input="$emit('input', $event)" :disabled="disabled" :loading="loading" />
</van-cell>
</template>
<script>
import Cell from '../cell';
import Switch from '../switch';
export default {
name: 'van-switch-cell',
components: {
[Cell.name]: Cell,
[Switch.name]: Switch
},
props: {
title: String,
value: Boolean,
loading: Boolean,
disabled: Boolean
},
watch: {
value() {
this.$emit('change', this.value);
}
}
};
</script>

View File

@ -1,21 +1,21 @@
<template>
<span class="van-tag" :class="[type ? `van-tag--${type}`: '', { 'is-plain': plain, 'is-mark': mark }]">
<span :class="['van-tag', { [`van-tag--${type}`]: type, 'is-plain': plain, 'is-mark': mark }]">
<slot></slot>
</span>
</template>
<script>
const ALLOW_TYPE = ['danger', 'success', 'primary'];
const ALLOW_TYPE = ['danger', 'success', 'primary'];
export default {
name: 'van-tag',
props: {
type: {
type: String,
validator: val => ~ALLOW_TYPE.indexOf(val)
},
mark: Boolean,
plain: Boolean
}
};
export default {
name: 'van-tag',
props: {
type: {
type: String,
validator: val => ~ALLOW_TYPE.indexOf(val)
},
mark: Boolean,
plain: Boolean
}
};
</script>

View File

@ -1,6 +1,6 @@
{
"name": "vant-css",
"version": "0.8.6",
"version": "0.8.9",
"description": "vant css.",
"main": "lib/index.css",
"style": "lib/index.css",

View File

@ -32,9 +32,7 @@
display: block;
}
&::after {
@mixin border-retina (top);
@mixin border-retina (right);
@mixin border-retina (left);
@mixin border-retina (top, right, left);
}
}

View File

@ -103,6 +103,7 @@
line-height: 50px;
border: 0;
border-radius: 0;
font-size: 16px;
color: $bottom-action-button-default-color;
background-color: $bottom-action-button-default-background-color;

View File

@ -37,6 +37,10 @@
&__title {
display: table-cell;
.van-icon {
margin-right: 5px;
}
}
&__label {

View File

@ -13,6 +13,7 @@ $c-yellow-light: #fcff00;
$c-orange: #f60;
$c-orange-dark: #f15a0c;
$c-blue: #38f;
$c-active: #e8e8e8;
$c-background: #f8f8f8;

View File

@ -0,0 +1,59 @@
@import "./mixins/ellipsis.css";
@import "./mixins/clearfix.css";
@import './common/var.css';
.van-deep-select {
user-select: none;
position: relative;
@mixin clearfix;
&__nav {
width: 143px;
/*float: left;*/
position: absolute;
left: 0;
top: 0;
bottom: 0;
overflow: scroll;
background-color: $c-white;
-webkit-overflow-scrolling: touch;
}
&__nitem {
line-height: 44px;
padding: 0 15px;
background-color: $c-white;
@mixin multi-ellipsis 1;
&--active {
background-color: $c-background;
}
}
&__content {
padding: 0 15px;
margin-left: 143px;
overflow: scroll;
-webkit-overflow-scrolling: touch;
}
&__item {
position: relative;
line-height: 44px;
padding-left: 5px;
padding-right: 18px;
@mixin multi-ellipsis 1;
&--active {
color: $button-danger-background-color;
}
}
&__selected {
float: right;
position: absolute;
right: 0px;
top: 0;
bottom: 0;
}
}

View File

@ -0,0 +1,58 @@
.van-express-way {
padding: 0;
&__fee,
&__type {
color: #666;
line-height: 1.5;
}
&__fee {
font-size: 14px;
}
&__type {
font-size: 12px;
}
.van-actionsheet__content {
max-height: 290px;
overflow-y: auto;
}
&-option {
position: relative;
padding: 14px 15px 14px 0;
.van-radio {
top: 50%;
left: 0;
margin-top: -11px;
position: absolute;
}
&__content {
padding-left: 30px;
p {
color: #999;
font-size: 12px;
line-height: 16px;
}
}
&__title {
span {
vertical-align: middle;
&:first-child {
margin-right: 5px;
}
}
}
&__warn {
color: #f09000;
}
}
}

View File

@ -0,0 +1,46 @@
@import './common/var.css';
@import './mixins/border_retina.css';
.van-goods-action {
left: 0;
right: 0;
bottom: 0;
display: flex;
position: fixed;
&__big-btn {
flex: 1;
}
&__mini-btn {
color: #666;
display: flex;
height: 50px;
font-size: 10px;
min-width: 15%;
position: relative;
text-align: center;
background-color: #fff;
flex-direction: column;
justify-content: center;
&::after {
@mixin border-retina (top, left), #cacaca;
}
&:first-child {
&::after {
border-left-width: 0;
}
}
&:active {
background-color: $c-active;
}
}
&__mini-btn-icon {
font-size: 20px;
margin-bottom: 5px;
}
}

View File

@ -6,6 +6,7 @@
@import './cell.css';
@import './cell-swipe.css';
@import './card.css';
@import './deep-select.css';
@import './dialog.css';
@import './field.css';
@import './icon.css';
@ -30,3 +31,10 @@
@import './toast.css';
@import './uploader.css';
@import './swipe.css';
@import './notice-bar.css';
@import './switch-cell.css';
@import './express-way.css';
@import './pay-order.css';
@import './order-goods.css';
@import './invalid-goods.css';
@import './goods-action.css';

View File

@ -0,0 +1,121 @@
@import "./mixins/ellipsis.css";
$van-invalid-goods-photo-size: 90px;
.van {
&-invalid-goods {
margin: 10px 0;
&__title {
color: #999;
font-size: 12px;
text-align: center;
margin-bottom: 10px;
}
&__container {
padding: 5px 10px;
}
&__gallery {
overflow: hidden;
height: $van-invalid-goods-photo-size;
}
&__thumb {
float: left;
display: flex;
height: 100%;
position: relative;
margin-right: 5px;
align-items: center;
justify-content: center;
img {
max-width: $van-invalid-goods-photo-size;
max-height: $van-invalid-goods-photo-size;
}
}
&__count {
position: absolute;
top: 0;
right: 0;
width: 80px;
color: #666;
font-size: 14px;
padding-right: 8px;
line-height: calc($van-invalid-goods-photo-size + 10px);
background-color: #fff;
text-align: right;
span {
margin-right: 6px;
vertical-align: middle;
}
}
&__list {
max-height: 400px;
overflow-y: scroll;
}
}
&-invalid-goods-card {
color: #999;
margin: 10px 0;
padding: 5px 10px;
background-color: #fafafa;
height: $van-invalid-goods-photo-size;
&__flag {
position: absolute;
left: 0;
top: 70px;
width: $van-invalid-goods-photo-size;
color: #fff;
font-size: 12px;
line-height: 20px;
text-align: center;
background-color: rgba(0,0,0,.6);
}
&__content {
width: 100%;
padding-left: 100px;
box-sizing: border-box;
}
&__row {
display: flex;
line-height: 20px;
}
&__title,
&__sku {
flex: 1;
@mixin multi-ellipsis 2;
}
&__title,
&__price {
font-size: 14px;
}
&__num,
&__sku {
font-size: 12px;
}
&__desc {
color: #f60;
font-size: 12px;
margin-top: 5px;
}
}
.van-icon-arrow {
color: #666;
font-size: 10px;
}
}

View File

@ -10,9 +10,8 @@
}
.van-loading {
line-height: 0;
font-size: 0;
line-height: 0;
&--circle {
width: 16px;
@ -26,11 +25,10 @@
}
&__spinner {
display: inline-block;
height: 100%;
width: 100%;
animation: van-loading 0.8s linear;
animation-iteration-count: infinite;
height: 100%;
display: inline-block;
animation: van-loading 0.8s linear infinite;
&--circle {
border-radius: 100%;

View File

@ -0,0 +1,36 @@
@import './common/var.css';
.van-notice-bar {
color: #f60;
padding: 9px 10px;
font-size: 12px;
line-height: 1.5;
background-color: #fff7cc;
&--withicon {
position: relative;
padding-right: 30px;
}
&__icon {
top: 10px;
right: 10px;
position: absolute;
font-size: 15px;
line-height: 1;
cursor: pointer;
}
&__content-wrap {
height: 18px;
overflow: hidden;
position: relative;
}
&__content {
position: absolute;
white-space: nowrap;
transition-property: left;
transition-timing-function: linear;
}
}

View File

@ -0,0 +1,214 @@
@import "./mixins/border_retina.css";
.van-order-goods {
background-color: #fff;
&-card {
margin-left: -15px;
position: relative;
background-color: #fafafa;
&:not(:first-child),
&__delivery {
&::after {
@mixin border-retina (top);
}
}
&__tags {
flex: 1;
}
&__tag-green,
&__tag-red {
font-size: 10px;
padding: 3px 5px;
margin-right: 5px;
border-radius: 2px;
display: inline-block;
}
&__tag-green {
color: #fff;
background-color: #4b0;
}
&__tag-red {
color: #ed5050;
padding: 5px 8px;
border: 1px solid #ed5050;
}
&__delivery {
padding-left: 15px;
background-color: transparent;
.van-cell__value {
color: #666;
}
}
&__present {
top: 0;
left: 3px;
width: 18px;
height: 36px;
position: absolute;
background: url("https://b.yzcdn.cn/v2/image/wap/trade/confirm/present@2x.png") no-repeat;
background-size: 18px 36px;
}
.van-button&__message-button {
height: 24px;
padding: 0 5px;
font-size: 10px;
line-height: 22px;
}
&__button {
padding: 20px 15px 0;
.van-button {
height: 40px;
line-height: 38px;
}
}
&__message {
width: 100%;
height: 100%;
background-color: #f8f8f8;
h2 {
color: #999;
font-size: 12px;
line-height: 18px;
padding: 5px 0 5px 10px;
}
ul {
background-color: #fff;
}
p,
a,
label {
font-size: 14px;
padding: 14px 0;
line-height: 20px;
vertical-align: top;
display: inline-block;
}
label {
color: #c9c9c9;
min-width: 90px;
}
li {
display: flex;
padding: 0 10px;
position: relative;
&:not(:last-child)::after {
@mixin border-retina (bottom);
}
img {
width: 70px;
height: 70px;
}
}
}
}
&-empty {
margin-left: -15px;
text-align: center;
position: relative;
&::after {
@mixin border-retina (top);
}
p {
color: #999;
padding: 0 10px;
font-size: 14px;
line-height: 20px;
}
img {
width: 80px;
height: 84px;
padding: 15px 0;
}
.van-button {
height: 41px;
margin: 15px 0;
padding: 0 10px;
line-height: 39px;
border-color: #e5e5e5;
}
}
&-header {
line-height: 50px;
a,
img,
.van-icon {
vertical-align: middle;
}
.van-icon {
font-size: 18px;
margin-right: 5px;
}
a {
color: #333;
font-size: 14px;
}
img {
height: 14px;
margin-left: 5px;
}
}
&-message {
textarea {
color: #666;
padding: 0;
width: 100%;
height: 22px;
border: none;
resize: none;
outline: none;
display: block;
font-size: 14px;
line-height: 22px;
transition: height .3s ease-in-out;
}
textarea&-focused {
height: 48px;
}
p {
color: #666;
text-align: left;
}
.van-cell__title {
width: 75px;
}
}
&-price {
.van-cell__value {
color: #f44;
}
}
}

View File

@ -0,0 +1,59 @@
.van-pay-order {
left: 0;
bottom: 0;
width: 100%;
z-index: 100;
position: fixed;
user-select: none;
&__tip {
color: #f60;
font-size: 12px;
line-height: 18px;
padding: 10px 10px;
background-color: #fff6e1;
}
&__bar {
height: 50px;
display: flex;
line-height: 50px;
background-color: #fff;
}
&__price {
flex: 1;
text-align: right;
padding-right: 10px;
}
&__price-text {
color: #666;
font-size: 16px;
}
&__price-interger {
color: #f44;
font-size: 16px;
}
&__price-decimal {
color: #f44;
font-size: 12px;
}
.van-button {
width: 110px;
height: 100%;
border-radius: 0;
&--disabled {
border: none;
}
.van-loading__spinner--white {
border-color: rgba(255,255,255, .8);
border-top-color: transparent;
}
}
}

View File

@ -0,0 +1,9 @@
.van-switch-cell {
.van-cell__title {
vertical-align: middle;
}
.van-switch {
float: right;
}
}

View File

@ -0,0 +1,37 @@
<template>
<van-goods-action>
<van-goods-action-mini-btn icon="chat" @click="onClickMiniBtn">
客服
</van-goods-action-mini-btn>
<van-goods-action-mini-btn icon="cart" url="http://www.youzan.com" @click="onClickMiniBtn">
购物车
</van-goods-action-mini-btn>
<van-goods-action-big-btn @click="onClickBigBtn">
加入购物车
</van-goods-action-big-btn>
<van-goods-action-big-btn @click="onClickBigBtn" primary url="http://www.youzan.com">
立即购买
</van-goods-action-big-btn>
</van-goods-action>
</template>
<script>
import GoodsAction from 'packages/goods-action';
import GoodsActionBigBtn from 'packages/goods-action-big-btn';
import GoodsActionMiniBtn from 'packages/goods-action-mini-btn';
export default {
components: {
[GoodsAction.name]: GoodsAction,
[GoodsActionBigBtn.name]: GoodsActionBigBtn,
[GoodsActionMiniBtn.name]: GoodsActionMiniBtn
},
methods: {
onClickMiniBtn() {
},
onClickBigBtn() {
}
}
};
</script>

View File

@ -0,0 +1,16 @@
<template>
<div class="notice-bar-container" style="width: 100px;">
<van-notice-bar :speed="speed" :text="text" :mode="mode" :delay="delay" />
</div>
</template>
<script>
import NoticeBar from 'packages/notice-bar';
export default {
components: {
[NoticeBar.name]: NoticeBar
},
props: ['speed', 'text', 'mode', 'delay']
};
</script>

View File

@ -35,7 +35,7 @@ function getWebpackConfig(testFileName) {
stats: 'errors-only',
resolve: {
modules: [path.resolve(process.cwd(), 'node_modules'), 'node_modules'],
extensions: ['.js', '.json', '.vue'],
extensions: ['.js', '.json', '.vue', '.css'],
alias: {
src: path.resolve(process.cwd(), 'src'),
packages: path.resolve(process.cwd(), 'packages'),
@ -75,7 +75,21 @@ function getWebpackConfig(testFileName) {
]
},
{
test: /\.vue$/,
test: /test\/unit\/components\/.*\.vue$|packages\/swipe\/.*\.vue$/,
use: [
{
loader: 'vue-loader',
options: {
loaders: {
css: ['style-loader', 'css-loader', 'postcss-loader']
}
}
}
]
},
{
test: /packages\/.*\.vue$/,
exclude: /packages\/swipe\/.*\.vue$/,
use: [
{
loader: 'vue-loader',

View File

@ -13,4 +13,4 @@ if (process.env.TEST_FILE) {
});
} else {
testsReq.keys().forEach(testsReq);
}
}

View File

@ -14,7 +14,8 @@ module.exports = function(config) {
reporters: ['spec', 'coverage'],
files: ['./index.js'],
preprocessors: {
'./index.js': ['webpack', 'sourcemap']
'./index.js': ['webpack', 'sourcemap'],
'test/unit/!(components)/**/*.vue': ['coverage']
},
webpack: getWebpackConfig(getTestFileName()),
webpackMiddleware: {

View File

@ -7,14 +7,14 @@ const defaultProps = {
leftWidth: 100,
rightWidth: 100
}
}
};
describe('CellSwipe', () => {
let wrapper;
afterEach(() => {
wrapper && wrapper.destroy();
});
it('render left or right part when has width', () => {
wrapper = mount(CellSwipe, defaultProps);
expect(wrapper.find('.van-cell-swipe__left').length).to.equal(1);
@ -97,7 +97,7 @@ describe('CellSwipe', () => {
triggerTouch(wrapper, 'touchstart', 0, 0);
triggerTouch(wrapper, 'touchmove', 1, 0);
wrapper.vm.$nextTick(() => {
expect(wrapper.vm.offset).to.equal(0);
expect(wrapper.vm.opened).to.be.false;

View File

@ -0,0 +1,68 @@
import DeepSelect from 'packages/deep-select';
import { mount } from 'avoriaz';
describe('DeepSelect', () => {
let wrapper;
afterEach(() => {
wrapper && wrapper.destroy();
});
it('create an empty deep-select', () => {
wrapper = mount(DeepSelect);
expect(wrapper.hasStyle('height', '0px')).to.be.true;
});
it('create a deep-select correctly', () => {
wrapper = mount(DeepSelect, {
propsData: {
items: [{
text: 'A',
children: [{
text: 'Cc',
id: 123
}]
}],
maxHeight: 200
}
});
expect(wrapper.hasClass('van-deep-select')).to.be.true;
expect(wrapper.hasStyle('height', '44px')).to.be.true;
expect(wrapper.propsData().maxHeight).to.equal(200);
});
it('interact with this component', () => {
wrapper = mount(DeepSelect, {
propsData: {
items: [{
text: 'A',
children: [{
text: 'Cc',
id: 123
}, {
text: 'Bb',
id: 234
}]
}, {
text: 'B',
children: [{
text: 'Nmi',
id: 345
}]
}],
maxHeight: 220
}
});
wrapper.vm.$on('navclick', index => {
wrapper.vm.mainActiveIndex = index;
});
wrapper.vm.$on('itemclick', item => {
wrapper.vm.activeId = item.id;
});
const secondNav = wrapper.find('.van-deep-select__nitem')[1];
secondNav.trigger('click');
expect(wrapper.vm.mainActiveIndex).to.equal(1);
const target = wrapper.find('.van-deep-select__item')[0];
target.trigger('click');
expect(wrapper.vm.activeId).to.equal(345);
});
});

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