mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-06 03:57:59 +08:00
Merge branch 'dev' of https://github.com/youzan/vant into dev
This commit is contained in:
commit
97d438ef1e
@ -1,16 +1,20 @@
|
||||
const path = require('path');
|
||||
const webpack = require('webpack');
|
||||
const config = require('./webpack.config.dev.js');
|
||||
const isMinify = process.argv.indexOf('-p') !== -1;
|
||||
|
||||
module.exports = Object.assign({}, config, {
|
||||
mode: 'production',
|
||||
entry: {
|
||||
'vant': './packages/index.js'
|
||||
},
|
||||
output: {
|
||||
filename: isMinify ? './lib/[name].min.js' : './lib/[name].js',
|
||||
path: path.join(__dirname, '../lib'),
|
||||
library: 'vant',
|
||||
libraryTarget: 'umd',
|
||||
umdNamedDefine: true
|
||||
filename: isMinify ? '[name].min.js' : '[name].js',
|
||||
umdNamedDefine: true,
|
||||
globalObject: 'this'
|
||||
},
|
||||
externals: {
|
||||
vue: {
|
||||
@ -20,10 +24,9 @@ module.exports = Object.assign({}, config, {
|
||||
amd: 'vue'
|
||||
}
|
||||
},
|
||||
plugins: [
|
||||
new webpack.DefinePlugin({
|
||||
'process.env.NODE_ENV': '"production"'
|
||||
}),
|
||||
new webpack.optimize.ModuleConcatenationPlugin()
|
||||
]
|
||||
plugins: [],
|
||||
performance: false,
|
||||
optimization: {
|
||||
minimize: isMinify
|
||||
}
|
||||
});
|
||||
|
@ -3,16 +3,10 @@ const webpack = require('webpack');
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
const ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||
const ProgressBarPlugin = require('progress-bar-webpack-plugin');
|
||||
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin');
|
||||
const isProduction = process.env.NODE_ENV === 'production';
|
||||
const cache = {
|
||||
loader: 'cache-loader',
|
||||
options: {
|
||||
cacheDirectory: path.resolve(__dirname, '../node_modules/.cache-loader')
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
mode: 'development',
|
||||
entry: {
|
||||
'vant-docs': './docs/src/index.js',
|
||||
'vant-mobile': './docs/src/mobile.js'
|
||||
@ -20,7 +14,6 @@ module.exports = {
|
||||
output: {
|
||||
path: path.join(__dirname, '../docs/dist'),
|
||||
publicPath: '/',
|
||||
filename: '[name].js',
|
||||
chunkFilename: 'async_[name].js'
|
||||
},
|
||||
devServer: {
|
||||
@ -34,21 +27,17 @@ module.exports = {
|
||||
stats: 'errors-only'
|
||||
},
|
||||
resolve: {
|
||||
modules: [path.join(__dirname, '../node_modules'), 'node_modules'],
|
||||
extensions: ['.js', '.vue', '.css'],
|
||||
alias: {
|
||||
vue: 'vue/dist/vue.runtime.esm.js',
|
||||
packages: path.join(__dirname, '../packages'),
|
||||
lib: path.join(__dirname, '../lib'),
|
||||
components: path.join(__dirname, '../docs/src/components')
|
||||
packages: path.join(__dirname, '../packages')
|
||||
}
|
||||
},
|
||||
module: {
|
||||
loaders: [
|
||||
rules: [
|
||||
{
|
||||
test: /\.vue$/,
|
||||
use: [
|
||||
cache,
|
||||
{
|
||||
loader: 'vue-loader',
|
||||
options: {
|
||||
@ -61,10 +50,7 @@ module.exports = {
|
||||
{
|
||||
test: /\.js$/,
|
||||
exclude: /node_modules|vue-router\/|vue-loader\//,
|
||||
use: [
|
||||
cache,
|
||||
'babel-loader'
|
||||
]
|
||||
use: 'babel-loader'
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
@ -78,7 +64,6 @@ module.exports = {
|
||||
{
|
||||
test: /\.md/,
|
||||
use: [
|
||||
cache,
|
||||
'vue-loader',
|
||||
'fast-vue-md-loader'
|
||||
]
|
||||
@ -103,15 +88,9 @@ module.exports = {
|
||||
filename: 'examples.html',
|
||||
inject: true
|
||||
}),
|
||||
new webpack.optimize.CommonsChunkPlugin({
|
||||
name: 'vendor',
|
||||
minChunks: 2,
|
||||
filename: isProduction ? 'vendor.[hash:8].js' : 'vendor.js'
|
||||
}),
|
||||
new ExtractTextPlugin({
|
||||
filename: isProduction ? '[name].[hash:8].css' : '[name].css',
|
||||
allChunks: true
|
||||
}),
|
||||
new FriendlyErrorsPlugin()
|
||||
})
|
||||
]
|
||||
};
|
||||
|
@ -4,19 +4,12 @@ const path = require('path');
|
||||
const devConfig = require('./webpack.config.dev.js');
|
||||
|
||||
module.exports = merge(devConfig, {
|
||||
mode: 'production',
|
||||
output: {
|
||||
path: path.join(__dirname, '../docs/dist'),
|
||||
publicPath: 'https://img.yzcdn.cn/zanui/vant/',
|
||||
filename: '[name].[hash:8].js',
|
||||
umdNamedDefine: true,
|
||||
chunkFilename: 'async_[name].[chunkhash:8].js'
|
||||
},
|
||||
plugins: [
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': {
|
||||
NODE_ENV: JSON.stringify(process.env.NODE_ENV)
|
||||
}
|
||||
}),
|
||||
new webpack.optimize.UglifyJsPlugin()
|
||||
]
|
||||
});
|
||||
|
3607
docs/demos/mock/area.js
Normal file
3607
docs/demos/mock/area.js
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
71
docs/demos/mock/areaEn.js
Normal file
71
docs/demos/mock/areaEn.js
Normal file
@ -0,0 +1,71 @@
|
||||
export default {
|
||||
'province_list': {
|
||||
'110000': 'Beijing',
|
||||
'330000': 'Zhejiang',
|
||||
'810000': 'Hong Kong'
|
||||
},
|
||||
'city_list': {
|
||||
'110100': 'Beijing City',
|
||||
'330100': 'Hangzhou',
|
||||
'330200': 'Ningbo',
|
||||
'330300': 'Wenzhou',
|
||||
'330400': 'Jiaxin',
|
||||
'331100': 'Lishui',
|
||||
'810100': 'Hong Kong Island',
|
||||
'810200': 'Kowloon',
|
||||
'810300': 'New Territories'
|
||||
},
|
||||
'county_list': {
|
||||
'110101': 'Dongcheng',
|
||||
'110102': 'Xicheng',
|
||||
'110105': 'Chaoyang',
|
||||
'110106': 'Fengtai',
|
||||
'110108': 'Haidian',
|
||||
'110111': 'Fangshan',
|
||||
'110112': 'Tongzhou',
|
||||
'110113': 'Shunyi',
|
||||
'110114': 'Changping',
|
||||
'110115': 'Daxing',
|
||||
'330105': 'Gongshu',
|
||||
'330106': 'Xihu',
|
||||
'330108': 'Binjiang',
|
||||
'330109': 'Xiaoshan',
|
||||
'330110': 'Yuhang',
|
||||
'330111': 'Fuyang',
|
||||
'330127': 'Chunan',
|
||||
'330182': 'Jiande',
|
||||
'330185': 'Linan',
|
||||
'330206': 'Beilun',
|
||||
'330211': 'Zhenhai',
|
||||
'330225': 'Xiangshan',
|
||||
'330226': 'Ninghai',
|
||||
'330281': 'Yuyao',
|
||||
'330282': 'Cixi',
|
||||
'330327': 'Cangnan',
|
||||
'330328': 'Wencheng',
|
||||
'330329': 'Shuntai',
|
||||
'330381': 'Ruian',
|
||||
'330382': 'Yueqing',
|
||||
'330402': 'Nanhu',
|
||||
'330421': 'Jiashan',
|
||||
'330424': 'Haiyan',
|
||||
'330481': 'Haining',
|
||||
'330482': 'Pinghu',
|
||||
'330483': 'Tongxiang',
|
||||
'331102': 'Liandu District',
|
||||
'331121': 'Qingtian County',
|
||||
'331125': 'Yunhe County',
|
||||
'331181': 'Longquan County',
|
||||
'810101': 'Central',
|
||||
'810102': 'Wan Chai',
|
||||
'810202': 'Mong Kok',
|
||||
'810203': 'Sham Shui Po',
|
||||
'810204': 'Chuk Un',
|
||||
'810205': 'Kwun Tong',
|
||||
'810303': 'Sha Tin',
|
||||
'810305': 'Yuen Long',
|
||||
'810306': 'Tuen Mun',
|
||||
'810307': 'Tsuen Wan',
|
||||
'810309': 'Lantau Island'
|
||||
}
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
{
|
||||
"province_list": {
|
||||
"110000": "Beijing",
|
||||
"330000": "Zhejiang",
|
||||
"810000": "Hong Kong"
|
||||
},
|
||||
"city_list": {
|
||||
"110100": "Beijing City",
|
||||
"330100": "Hangzhou",
|
||||
"330200": "Ningbo",
|
||||
"330300": "Wenzhou",
|
||||
"330400": "Jiaxin",
|
||||
"331100": "Lishui",
|
||||
"810100": "Hong Kong Island",
|
||||
"810200": "Kowloon",
|
||||
"810300": "New Territories"
|
||||
},
|
||||
"county_list": {
|
||||
"110101": "Dongcheng",
|
||||
"110102": "Xicheng",
|
||||
"110105": "Chaoyang",
|
||||
"110106": "Fengtai",
|
||||
"110108": "Haidian",
|
||||
"110111": "Fangshan",
|
||||
"110112": "Tongzhou",
|
||||
"110113": "Shunyi",
|
||||
"110114": "Changping",
|
||||
"110115": "Daxing",
|
||||
"330105": "Gongshu",
|
||||
"330106": "Xihu",
|
||||
"330108": "Binjiang",
|
||||
"330109": "Xiaoshan",
|
||||
"330110": "Yuhang",
|
||||
"330111": "Fuyang",
|
||||
"330127": "Chunan",
|
||||
"330182": "Jiande",
|
||||
"330185": "Linan",
|
||||
"330206": "Beilun",
|
||||
"330211": "Zhenhai",
|
||||
"330225": "Xiangshan",
|
||||
"330226": "Ninghai",
|
||||
"330281": "Yuyao",
|
||||
"330282": "Cixi",
|
||||
"330327": "Cangnan",
|
||||
"330328": "Wencheng",
|
||||
"330329": "Shuntai",
|
||||
"330381": "Ruian",
|
||||
"330382": "Yueqing",
|
||||
"330402": "Nanhu",
|
||||
"330421": "Jiashan",
|
||||
"330424": "Haiyan",
|
||||
"330481": "Haining",
|
||||
"330482": "Pinghu",
|
||||
"330483": "Tongxiang",
|
||||
"331102": "Liandu District",
|
||||
"331121": "Qingtian County",
|
||||
"331125": "Yunhe County",
|
||||
"331181": "Longquan County",
|
||||
"810101": "Central",
|
||||
"810102": "Wan Chai",
|
||||
"810202": "Mong Kok",
|
||||
"810203": "Sham Shui Po",
|
||||
"810204": "Chuk Un",
|
||||
"810205": "Kwun Tong",
|
||||
"810303": "Sha Tin",
|
||||
"810305": "Yuen Long",
|
||||
"810306": "Tuen Mun",
|
||||
"810307": "Tsuen Wan",
|
||||
"810309": "Lantau Island"
|
||||
}
|
||||
}
|
@ -16,7 +16,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import areaList from '../mock/area.json';
|
||||
import areaList from '../mock/area';
|
||||
|
||||
export default {
|
||||
i18n: {
|
||||
|
@ -15,8 +15,8 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import AreaList from '../mock/area.json';
|
||||
import AreaListEn from '../mock/areaEn.json';
|
||||
import AreaList from '../mock/area';
|
||||
import AreaListEn from '../mock/areaEn';
|
||||
|
||||
export default {
|
||||
i18n: {
|
||||
|
@ -54,7 +54,7 @@ export default {
|
||||
step2: '商家接单',
|
||||
step3: '买家提货',
|
||||
step4: '交易完成',
|
||||
title2: '物流描述',
|
||||
title2: '描述信息',
|
||||
title3: '竖向步骤条',
|
||||
status1: '【城市】物流状态1',
|
||||
status2: '【城市】物流状态',
|
||||
|
@ -58,6 +58,14 @@
|
||||
</van-tab>
|
||||
</van-tabs>
|
||||
</demo-block>
|
||||
|
||||
<demo-block :title="$t('title8')">
|
||||
<van-tabs :active="active" swipeable>
|
||||
<van-tab :title="$t('tab') + index" v-for="index in tabs" :key="index">
|
||||
{{ $t('content') }} {{ index }}
|
||||
</van-tab>
|
||||
</van-tabs>
|
||||
</demo-block>
|
||||
</demo-section>
|
||||
</template>
|
||||
|
||||
@ -71,7 +79,8 @@ export default {
|
||||
title4: '样式风格',
|
||||
title5: '点击事件',
|
||||
title6: '粘性布局',
|
||||
title7: '自定义标签'
|
||||
title7: '自定义标签',
|
||||
title8: '滑动切换'
|
||||
},
|
||||
'en-US': {
|
||||
tab: 'Tab ',
|
||||
@ -81,7 +90,8 @@ export default {
|
||||
title4: 'Card Style',
|
||||
title5: 'Click Event',
|
||||
title6: 'Sticky',
|
||||
title7: 'Custom Tab'
|
||||
title7: 'Custom Tab',
|
||||
title8: 'Swipeable'
|
||||
}
|
||||
},
|
||||
|
||||
@ -106,7 +116,7 @@ export default {
|
||||
|
||||
<style lang="postcss">
|
||||
.demo-tab {
|
||||
margin-bottom: 500px;
|
||||
margin-bottom: 300px;
|
||||
|
||||
.van-tab .van-icon {
|
||||
margin-right: 5px;
|
||||
|
@ -86,7 +86,7 @@ Example of `AreaList`
|
||||
}
|
||||
```
|
||||
|
||||
All code of China: [Area.json](https://github.com/youzan/vant/blob/dev/docs/demos/mock/area.json)
|
||||
All code of China: [Area.json](https://github.com/youzan/vant/blob/dev/docs/demos/mock/area.js)
|
||||
|
||||
#### argument of callback function confirm
|
||||
An array contains selected area objects.
|
||||
|
@ -124,6 +124,18 @@ Use title slot to custom tab title
|
||||
</van-tabs>
|
||||
```
|
||||
|
||||
#### Swipeable
|
||||
|
||||
In swipeable mode, you can switch tabs with swipe gestrue in the content
|
||||
|
||||
```html
|
||||
<van-tabs :active="active" swipeable>
|
||||
<van-tab v-for="index in 4" :title="'tab ' + index">
|
||||
content {{ index }}
|
||||
</van-tab>
|
||||
</van-tabs>
|
||||
```
|
||||
|
||||
### Tabs API
|
||||
|
||||
| Attribute | Description | Type | Default | Accepted Values |
|
||||
@ -132,6 +144,8 @@ Use title slot to custom tab title
|
||||
| active | Index of active tab | `String` `Number` | `0` | - |
|
||||
| duration | Toggle tab's animation time | `Number` | `0.2` | - | - |
|
||||
| swipe-threshold | Set swipe tabs threshold | `Number` | `4` | - | - |
|
||||
| sticky | Whether to use sticky mode | `Boolean` | `false` | - |
|
||||
| swipeable | Whether to switch tabs with swipe gestrue in the content | `Boolean` | `false` | - |
|
||||
|
||||
### Tab API
|
||||
|
||||
|
@ -90,7 +90,7 @@ Vue.use(Area);
|
||||
}
|
||||
```
|
||||
|
||||
完整数据见 [Area.json](https://github.com/youzan/vant/blob/dev/docs/demos/mock/area.json)
|
||||
完整数据见 [Area.json](https://github.com/youzan/vant/blob/dev/docs/demos/mock/area.js)
|
||||
|
||||
#### 点击完成时返回的数据格式
|
||||
|
||||
|
@ -15,10 +15,10 @@ Vue.use(Badge);
|
||||
|
||||
```html
|
||||
<van-badge-group :active-key="activeKey">
|
||||
<van-badge title="热销榜" @click="onClick" />
|
||||
<van-badge title="花式寿司" @click="onClick" info="8" />
|
||||
<van-badge title="火炽寿司" @click="onClick" info="99" />
|
||||
<van-badge title="手握寿司" @click="onClick" info="199" />
|
||||
<van-badge title="标签名称" @click="onClick" />
|
||||
<van-badge title="标签名称" @click="onClick" info="8" />
|
||||
<van-badge title="标签名称" @click="onClick" info="99" />
|
||||
<van-badge title="标签名称" @click="onClick" info="199" />
|
||||
</van-badge-group>
|
||||
```
|
||||
|
||||
|
@ -86,7 +86,7 @@ Vue.use(Field);
|
||||
placeholder="请输入留言"
|
||||
rows="1"
|
||||
autosize
|
||||
/>
|
||||
/>
|
||||
</van-cell-group>
|
||||
```
|
||||
|
||||
|
@ -30,9 +30,9 @@ export default {
|
||||
}
|
||||
```
|
||||
|
||||
#### 物流描述
|
||||
#### 描述信息
|
||||
|
||||
通过`title`和`description`属性来定义物流描述信息
|
||||
通过`title`和`description`属性来定义描述信息信息
|
||||
|
||||
```html
|
||||
<van-steps
|
||||
|
@ -124,6 +124,18 @@ export default {
|
||||
</van-tabs>
|
||||
```
|
||||
|
||||
#### 滑动切换
|
||||
|
||||
通过`swipeable`属性可以开启滑动切换tab
|
||||
|
||||
```html
|
||||
<van-tabs :active="active" swipeable>
|
||||
<van-tab v-for="index in 4" :title="'选项 ' + index">
|
||||
内容 {{ index }}
|
||||
</van-tab>
|
||||
</van-tabs>
|
||||
```
|
||||
|
||||
### Tabs API
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 | 可选 |
|
||||
@ -133,6 +145,7 @@ export default {
|
||||
| duration | 切换 tab 的动画时间 | `Number` | `0.2` | - |
|
||||
| swipe-threshold | 滚动阀值,设置 Tab 超过多少个可滚动 | `Number` | `4` | - |
|
||||
| sticky | 是否使用粘性定位布局 | `Boolean` | `false` | - |
|
||||
| swipeable | 是否可以滑动内容切换 | `Boolean` | `false` | - |
|
||||
|
||||
### Tab API
|
||||
|
||||
|
27
package.json
27
package.json
@ -13,12 +13,12 @@
|
||||
],
|
||||
"scripts": {
|
||||
"bootstrap": "yarn || npm i && cd ./packages/vant-css/ && yarn || npm i && cd ../../",
|
||||
"dev": "npm run build:file && webpack-dev-server --inline --config build/webpack.config.dev.js --content-base ./",
|
||||
"dev": "npm run build:file && webpack-dev-server --inline --config build/webpack.config.dev.js",
|
||||
"build:file": "node build/bin/build-entry.js",
|
||||
"build:components": "node build/bin/build-components.js --color",
|
||||
"build:vant-css": "gulp build --gulpfile packages/vant-css/gulpfile.js --color",
|
||||
"build:vant": "cross-env NODE_ENV=production webpack --progress --hide-modules --color --config build/webpack.build.js && cross-env NODE_ENV=production webpack -p --progress --hide-modules --color --config build/webpack.build.js",
|
||||
"build:style-entry": "cross-env VUE_ENV=server node build/bin/build-style-entry.js",
|
||||
"build:style-entry": "node build/bin/build-style-entry.js",
|
||||
"build:changelog": "sh build/bin/build-changelog.sh",
|
||||
"deploy": "npm run deploy:docs && npm run deploy:cdn && gh-pages -d docs/dist --remote youzan && rimraf docs/dist",
|
||||
"deploy:cdn": "superman cdn /zanui/vant docs/dist/*.js docs/dist/*.css && superman cdn /zanui/vant/async_en-US docs/dist/async_en-US/*.js && superman cdn /zanui/vant/async_zh-CN docs/dist/async_zh-CN/*.js",
|
||||
@ -59,29 +59,27 @@
|
||||
"babel-plugin-transform-runtime": "^6.15.0",
|
||||
"babel-polyfill": "^6.26.0",
|
||||
"babel-preset-env": "^1.6.1",
|
||||
"cache-loader": "^1.2.2",
|
||||
"chai": "^4.1.2",
|
||||
"codecov": "^3.0.0",
|
||||
"cross-env": "^5.1.3",
|
||||
"cross-env": "^5.1.4",
|
||||
"css-loader": "^0.28.10",
|
||||
"dependency-tree": "^6.0.1",
|
||||
"eslint": "^4.18.2",
|
||||
"eslint-plugin-vue": "^4.3.0",
|
||||
"extract-text-webpack-plugin": "3.0.2",
|
||||
"extract-text-webpack-plugin": "^4.0.0-beta.0",
|
||||
"fast-vue-md-loader": "^1.0.3",
|
||||
"friendly-errors-webpack-plugin": "^1.6.1",
|
||||
"gh-pages": "^1.0.0",
|
||||
"html-webpack-plugin": "^3.0.6",
|
||||
"html-webpack-plugin": "3.0.6",
|
||||
"isparta-loader": "^2.0.0",
|
||||
"karma": "^1.7.1",
|
||||
"karma": "^2.0.0",
|
||||
"karma-chrome-launcher": "^2.2.0",
|
||||
"karma-coverage": "^1.1.1",
|
||||
"karma-mocha": "^1.3.0",
|
||||
"karma-phantomjs-launcher": "^1.0.4",
|
||||
"karma-sinon-chai": "^1.3.2",
|
||||
"karma-spec-reporter": "^0.0.32",
|
||||
"karma-webpack": "^2.0.9",
|
||||
"mocha": "^4.0.1",
|
||||
"karma-webpack": "^2.0.13",
|
||||
"mocha": "^5.0.4",
|
||||
"postcss": "^6.0.19",
|
||||
"postcss-calc": "^6.0.0",
|
||||
"postcss-easy-import": "^3.0.0",
|
||||
@ -96,15 +94,16 @@
|
||||
"uppercamelcase": "^3.0.0",
|
||||
"url-loader": "^1.0.1",
|
||||
"vant-doc": "1.0.4",
|
||||
"vue": "^2.5.15",
|
||||
"vue": "^2.5.16",
|
||||
"vue-loader": "^14.2.1",
|
||||
"vue-router": "^3.0.1",
|
||||
"vue-sfc-compiler": "^0.0.8",
|
||||
"vue-style-loader": "^4.0.2",
|
||||
"vue-template-compiler": "^2.5.15",
|
||||
"vue-template-compiler": "^2.5.16",
|
||||
"vue-template-es2015-compiler": "^1.6.0",
|
||||
"webpack": "^3.11.0",
|
||||
"webpack-dev-server": "2.11.1",
|
||||
"webpack": "^4.1.1",
|
||||
"webpack-cli": "^2.0.12",
|
||||
"webpack-dev-server": "3.1.1",
|
||||
"webpack-merge": "^4.1.2"
|
||||
}
|
||||
}
|
||||
|
@ -103,6 +103,7 @@ export default create({
|
||||
onInput(event) {
|
||||
const { value } = event.target;
|
||||
this.currentValue = value ? this.correctValue(+value) : value;
|
||||
event.target.value = this.currentValue;
|
||||
this.emitInput();
|
||||
},
|
||||
|
||||
|
@ -26,7 +26,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="van-tabs__content">
|
||||
<div class="van-tabs__content" ref="content">
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
@ -63,7 +63,8 @@ export default create({
|
||||
swipeThreshold: {
|
||||
type: Number,
|
||||
default: 4
|
||||
}
|
||||
},
|
||||
swipeable: Boolean
|
||||
},
|
||||
|
||||
data() {
|
||||
@ -115,6 +116,9 @@ export default create({
|
||||
if (this.sticky) {
|
||||
this.scrollHandler(true);
|
||||
}
|
||||
if (this.swipeable) {
|
||||
this.swipeableHandler(true);
|
||||
}
|
||||
this.scrollIntoView();
|
||||
});
|
||||
},
|
||||
@ -124,6 +128,10 @@ export default create({
|
||||
if (this.sticky) {
|
||||
this.scrollHandler(false);
|
||||
}
|
||||
/* istanbul ignore next */
|
||||
if (this.swipeable) {
|
||||
this.swipeableHandler(false);
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
@ -136,6 +144,53 @@ export default create({
|
||||
}
|
||||
},
|
||||
|
||||
// whether to bind content swipe listener
|
||||
swipeableHandler(init) {
|
||||
const swipeableEl = this.$refs.content;
|
||||
|
||||
(init ? on : off)(swipeableEl, 'touchstart', this.onTouchStart, false);
|
||||
(init ? on : off)(swipeableEl, 'touchmove', this.onTouchMove, false);
|
||||
(init ? on : off)(swipeableEl, 'touchend', this.onTouchEnd, false);
|
||||
(init ? on : off)(swipeableEl, 'touchcancel', this.onTouchEnd, false);
|
||||
},
|
||||
|
||||
// record swipe touch start position
|
||||
onTouchStart(event) {
|
||||
this.startX = event.touches[0].clientX;
|
||||
this.startY = event.touches[0].clientY;
|
||||
},
|
||||
|
||||
// watch swipe touch move
|
||||
onTouchMove(event) {
|
||||
event.preventDefault();
|
||||
this.deltaX = event.touches[0].clientX - this.startX;
|
||||
this.direction = this.getDirection(event.touches[0]);
|
||||
},
|
||||
|
||||
// watch swipe touch end
|
||||
onTouchEnd(event) {
|
||||
event.preventDefault();
|
||||
const { direction, deltaX, curActive } = this;
|
||||
const minSwipeDistance = 50;
|
||||
|
||||
/* istanbul ignore else */
|
||||
if (direction === 'horizontal' && Math.abs(deltaX) >= minSwipeDistance) {
|
||||
/* istanbul ignore else */
|
||||
if (deltaX > 0 && curActive !== 0) {
|
||||
this.curActive = curActive - 1;
|
||||
} else if (deltaX < 0 && curActive !== this.tabs.length - 1) {
|
||||
this.curActive = curActive + 1;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// get swipe direction
|
||||
getDirection(touch) {
|
||||
const distanceX = Math.abs(touch.clientX - this.startX);
|
||||
const distanceY = Math.abs(touch.clientY - this.startY);
|
||||
return distanceX > distanceY ? 'horizontal' : distanceX < distanceY ? 'vertical' : '';
|
||||
},
|
||||
|
||||
// adjust tab position
|
||||
onScroll() {
|
||||
const scrollTop = scrollUtils.getScrollTop(this.scrollEl);
|
||||
|
BIN
packages/vant-css/src/vant-icon-743c0e.ttf
Normal file
BIN
packages/vant-css/src/vant-icon-743c0e.ttf
Normal file
Binary file not shown.
@ -1,5 +1,12 @@
|
||||
<template>
|
||||
<van-tabs :active="active" :duration="duration" @click="handleTabClick" @disabled="handleTabDisabledClick" :sticky="sticky">
|
||||
<van-tabs
|
||||
:active="active"
|
||||
:duration="duration"
|
||||
:sticky="sticky"
|
||||
:swipeable="swipeable"
|
||||
@click="handleTabClick"
|
||||
@disabled="handleTabDisabledClick"
|
||||
>
|
||||
<van-tab :title="firstTabTitle" :disabled="firstTabDisabled">内容一</van-tab>
|
||||
<van-tab title="选项二">内容二</van-tab>
|
||||
<van-tab title="选项三" disabled>内容三</van-tab>
|
||||
@ -17,7 +24,8 @@ export default {
|
||||
firstTabDisabled: {
|
||||
type: Boolean
|
||||
},
|
||||
sticky: Boolean
|
||||
sticky: Boolean,
|
||||
swipeable: Boolean
|
||||
},
|
||||
|
||||
data() {
|
||||
|
@ -4,6 +4,7 @@ const ProgressBarPlugin = require('progress-bar-webpack-plugin');
|
||||
|
||||
function getWebpackConfig(testFileName) {
|
||||
return {
|
||||
mode: 'development',
|
||||
output: {
|
||||
path: path.resolve(process.cwd(), 'dist'),
|
||||
publicPath: '/dist/',
|
||||
@ -18,7 +19,7 @@ function getWebpackConfig(testFileName) {
|
||||
options: {
|
||||
babel: {
|
||||
presets: ['env'],
|
||||
plugins: ['transform-runtime']
|
||||
plugins: ['transform-runtime', 'transform-object-rest-spread']
|
||||
},
|
||||
vue: {
|
||||
autoprefixer: false,
|
||||
@ -35,7 +36,7 @@ function getWebpackConfig(testFileName) {
|
||||
stats: 'errors-only',
|
||||
resolve: {
|
||||
modules: [path.resolve(process.cwd(), 'node_modules'), 'node_modules'],
|
||||
extensions: ['.js', '.json', '.vue', '.css'],
|
||||
extensions: ['.js', '.vue', '.css'],
|
||||
alias: {
|
||||
src: path.resolve(process.cwd(), 'src'),
|
||||
packages: path.resolve(process.cwd(), 'packages'),
|
||||
@ -48,12 +49,12 @@ function getWebpackConfig(testFileName) {
|
||||
enforce: 'pre',
|
||||
test: /\.js$/,
|
||||
exclude: /node_modules|vue-router\/|vue-loader\/|docs|test|src\/index|src\/utils|src\/mixins|packages\/swipe/,
|
||||
use: ['isparta-loader']
|
||||
use: 'isparta-loader'
|
||||
},
|
||||
{
|
||||
test: /\.js$/,
|
||||
exclude: /node_modules|vue-router\/|vue-loader\//,
|
||||
use: ['babel-loader']
|
||||
use: 'babel-loader'
|
||||
},
|
||||
{
|
||||
test: /\.(css|pcss)$/,
|
||||
@ -111,8 +112,7 @@ function getWebpackConfig(testFileName) {
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
devtool: '#inline-source-map'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { mount } from 'avoriaz';
|
||||
import AddressEdit from 'packages/address-edit';
|
||||
import AddressDetail from 'packages/address-edit/Detail';
|
||||
import areaList from '../../docs/demos/mock/area.json';
|
||||
import areaList from '../../docs/demos/mock/area';
|
||||
|
||||
describe('AddressEdit', () => {
|
||||
let wrapper;
|
||||
|
@ -1,6 +1,6 @@
|
||||
import Area from 'packages/area';
|
||||
import { mount } from 'avoriaz';
|
||||
import areaList from '../../docs/demos/mock/area.json';
|
||||
import areaList from '../../docs/demos/mock/area';
|
||||
|
||||
describe('Area', () => {
|
||||
let wrapper;
|
||||
|
@ -2,6 +2,7 @@ import Tabs from 'packages/tabs';
|
||||
import { mount } from 'avoriaz';
|
||||
import TabsTestComponent from '../components/tabs';
|
||||
import MoreTabsTestComponent from '../components/more-tabs';
|
||||
import { triggerTouch } from '../utils';
|
||||
|
||||
describe('Tabs', () => {
|
||||
let wrapper;
|
||||
@ -114,7 +115,7 @@ describe('Tabs', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('sticky', (done) => {
|
||||
it('create a sticky tabs', (done) => {
|
||||
wrapper = mount(TabsTestComponent, {
|
||||
attachToDocument: true,
|
||||
propsData: {
|
||||
@ -129,4 +130,37 @@ describe('Tabs', () => {
|
||||
done();
|
||||
}, 30);
|
||||
});
|
||||
|
||||
it('create a swipeable tabs', (done) => {
|
||||
wrapper = mount(TabsTestComponent, {
|
||||
attachToDocument: true,
|
||||
propsData: {
|
||||
swipeable: true
|
||||
}
|
||||
});
|
||||
|
||||
const tabsContainer = wrapper.find('.van-tabs')[0];
|
||||
const tabContent = wrapper.find('.van-tabs__content')[0];
|
||||
|
||||
expect(tabsContainer.vNode.child.curActive).to.equal(0);
|
||||
|
||||
wrapper.vm.$nextTick(() => {
|
||||
triggerTouch(tabContent, 'touchstart', 0, 0);
|
||||
triggerTouch(tabContent, 'touchmove', -100, 0);
|
||||
triggerTouch(tabContent, 'touchend', 0, 0);
|
||||
|
||||
setTimeout(() => {
|
||||
expect(tabsContainer.vNode.child.curActive).to.equal(1);
|
||||
|
||||
triggerTouch(tabContent, 'touchstart', 0, 0);
|
||||
triggerTouch(tabContent, 'touchmove', 100, 0);
|
||||
triggerTouch(tabContent, 'touchend', 0, 0);
|
||||
|
||||
setTimeout(() => {
|
||||
expect(tabsContainer.vNode.child.curActive).to.equal(0);
|
||||
done();
|
||||
}, 500);
|
||||
}, 500);
|
||||
})
|
||||
});
|
||||
});
|
||||
|
@ -49,7 +49,7 @@ describe('Utils', () => {
|
||||
raf(spy);
|
||||
|
||||
setTimeout(() => {
|
||||
expect(spy.calledOnce).to.be.true;
|
||||
expect(spy.called).to.be.true;
|
||||
cancel(1);
|
||||
done();
|
||||
}, 50);
|
||||
|
3
types/index.d.ts
vendored
3
types/index.d.ts
vendored
@ -22,6 +22,8 @@ export class CellSwipe extends VanComponent {}
|
||||
export class Checkbox extends VanComponent {}
|
||||
export class CheckboxGroup extends VanComponent {}
|
||||
export class Col extends VanComponent {}
|
||||
export class Collapse extends VanComponent {}
|
||||
export class CollapseItem extends VanComponent {}
|
||||
export class ContactCard extends VanComponent {}
|
||||
export class ContactEdit extends VanComponent {}
|
||||
export class ContactList extends VanComponent {}
|
||||
@ -33,6 +35,7 @@ export class GoodsAction extends VanComponent {}
|
||||
export class GoodsActionBigBtn extends VanComponent {}
|
||||
export class GoodsActionMiniBtn extends VanComponent {}
|
||||
export class Icon extends VanComponent {}
|
||||
export class List extends VanComponent {}
|
||||
export class Loading extends VanComponent {}
|
||||
export class NavBar extends VanComponent {}
|
||||
export class NoticeBar extends VanComponent {}
|
||||
|
Loading…
x
Reference in New Issue
Block a user