mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-06 03:57:59 +08:00
Merge branch 'origin/dev' into dev
This commit is contained in:
commit
2327e75516
@ -5,6 +5,7 @@
|
|||||||
<p align="center">
|
<p align="center">
|
||||||
<img alt="项目logo" src="https://img.yzcdn.cn/upload_files/2017/04/20/FlkVrSlOr-SGK9qQqtilN6-IFZyT.png">
|
<img alt="项目logo" src="https://img.yzcdn.cn/upload_files/2017/04/20/FlkVrSlOr-SGK9qQqtilN6-IFZyT.png">
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p align="center">A Vue.js 2.0 Mobile UI at YouZan</p>
|
<p align="center">A Vue.js 2.0 Mobile UI at YouZan</p>
|
||||||
|
|
||||||
[](https://travis-ci.org/youzan/vant)
|
[](https://travis-ci.org/youzan/vant)
|
||||||
|
@ -5,6 +5,12 @@ const ExtractTextPlugin = require('extract-text-webpack-plugin');
|
|||||||
const ProgressBarPlugin = require('progress-bar-webpack-plugin');
|
const ProgressBarPlugin = require('progress-bar-webpack-plugin');
|
||||||
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin');
|
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin');
|
||||||
const isProduction = process.env.NODE_ENV === 'production';
|
const isProduction = process.env.NODE_ENV === 'production';
|
||||||
|
const cache = {
|
||||||
|
loader: 'cache-loader',
|
||||||
|
options: {
|
||||||
|
cacheDirectory: path.resolve(__dirname, '../node_modules/.cache-loader')
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
entry: {
|
entry: {
|
||||||
@ -16,7 +22,6 @@ module.exports = {
|
|||||||
path: path.join(__dirname, '../docs/dist'),
|
path: path.join(__dirname, '../docs/dist'),
|
||||||
publicPath: '/',
|
publicPath: '/',
|
||||||
filename: '[name].js',
|
filename: '[name].js',
|
||||||
umdNamedDefine: true,
|
|
||||||
chunkFilename: 'async_[name].js'
|
chunkFilename: 'async_[name].js'
|
||||||
},
|
},
|
||||||
devServer: {
|
devServer: {
|
||||||
@ -44,6 +49,7 @@ module.exports = {
|
|||||||
{
|
{
|
||||||
test: /\.vue$/,
|
test: /\.vue$/,
|
||||||
use: [
|
use: [
|
||||||
|
cache,
|
||||||
{
|
{
|
||||||
loader: 'vue-loader',
|
loader: 'vue-loader',
|
||||||
options: {
|
options: {
|
||||||
@ -57,6 +63,7 @@ module.exports = {
|
|||||||
test: /\.js$/,
|
test: /\.js$/,
|
||||||
exclude: /node_modules|vue-router\/|vue-loader\//,
|
exclude: /node_modules|vue-router\/|vue-loader\//,
|
||||||
use: [
|
use: [
|
||||||
|
cache,
|
||||||
'babel-loader'
|
'babel-loader'
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -72,6 +79,7 @@ module.exports = {
|
|||||||
{
|
{
|
||||||
test: /\.md/,
|
test: /\.md/,
|
||||||
use: [
|
use: [
|
||||||
|
cache,
|
||||||
'vue-loader',
|
'vue-loader',
|
||||||
'fast-vue-md-loader'
|
'fast-vue-md-loader'
|
||||||
]
|
]
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
</demo-block>
|
</demo-block>
|
||||||
|
|
||||||
<demo-block :title="$t('title2')">
|
<demo-block :title="$t('title2')">
|
||||||
<van-area :areaList="areaList" value="110101" />
|
<van-area :areaList="areaList" :value="value" />
|
||||||
</demo-block>
|
</demo-block>
|
||||||
|
|
||||||
<demo-block :title="$t('title3')">
|
<demo-block :title="$t('title3')">
|
||||||
@ -31,7 +31,8 @@ export default {
|
|||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
areaList: AreaList
|
areaList: AreaList,
|
||||||
|
value: '110101'
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,19 +1,26 @@
|
|||||||
<template>
|
<template>
|
||||||
<demo-section>
|
<demo-section>
|
||||||
<demo-block :title="$t('basicUsage')">
|
<demo-block :title="$t('basicUsage')">
|
||||||
<van-picker :columns="columns" @change="onChange" />
|
<van-picker :columns="$t('column1')" @change="onChange1" />
|
||||||
</demo-block>
|
</demo-block>
|
||||||
|
|
||||||
<demo-block :title="$t('title2')">
|
<demo-block :title="$t('title2')">
|
||||||
|
<van-picker :columns="$t('column2')" />
|
||||||
|
</demo-block>
|
||||||
|
|
||||||
|
<demo-block :title="$t('title3')">
|
||||||
<van-picker
|
<van-picker
|
||||||
showToolbar
|
showToolbar
|
||||||
:title="$t('area')"
|
:title="$t('area')"
|
||||||
:columns="columns"
|
:columns="$t('column1')"
|
||||||
@change="onChange"
|
|
||||||
@cancel="onCancel"
|
@cancel="onCancel"
|
||||||
@confirm="onConfirm"
|
@confirm="onConfirm"
|
||||||
/>
|
/>
|
||||||
</demo-block>
|
</demo-block>
|
||||||
|
|
||||||
|
<demo-block :title="$t('title4')">
|
||||||
|
<van-picker :columns="columns" @change="onChange2" />
|
||||||
|
</demo-block>
|
||||||
</demo-section>
|
</demo-section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -21,26 +28,45 @@
|
|||||||
export default {
|
export default {
|
||||||
i18n: {
|
i18n: {
|
||||||
'zh-CN': {
|
'zh-CN': {
|
||||||
area: '地区选择',
|
area: '标题',
|
||||||
title2: '带 toolbar 的 Picker',
|
title2: '禁用选项',
|
||||||
column: {
|
title3: '展示顶部栏',
|
||||||
'浙江': ['杭州', '宁波', '温州', '嘉兴', '湖州', '绍兴', '金华', '衢州'],
|
title4: '多列联动',
|
||||||
'福建': ['福州', '厦门', '莆田', '三明', '泉州', '漳州', '南平', '龙岩']
|
column1: ['杭州', '宁波', '温州', '嘉兴', '湖州'],
|
||||||
}
|
column2: [
|
||||||
|
{ text: '杭州', disabled: true },
|
||||||
|
{ text: '宁波' },
|
||||||
|
{ text: '温州' }
|
||||||
|
],
|
||||||
|
column3: {
|
||||||
|
浙江: ['杭州', '宁波', '温州', '嘉兴', '湖州'],
|
||||||
|
福建: ['福州', '厦门', '莆田', '三明', '泉州']
|
||||||
|
},
|
||||||
|
toastContent: (value, index) => `当前值:${value}, 当前索引:${index}`
|
||||||
},
|
},
|
||||||
'en-US': {
|
'en-US': {
|
||||||
area: 'Title',
|
area: 'Title',
|
||||||
|
title2: 'Disable Option',
|
||||||
|
title3: 'Show Toolbar',
|
||||||
|
title4: 'Multi Columns',
|
||||||
title2: 'Picker with toolbar',
|
title2: 'Picker with toolbar',
|
||||||
column: {
|
column1: ['Delaware', 'Florida', 'Georqia', 'Indiana', 'Maine'],
|
||||||
'Group1': ['Delaware', 'Florida', 'Georqia', 'Indiana', 'Maine'],
|
column2: [
|
||||||
'Group2': ['Alabama', 'Kansas', 'Louisiana', 'Texas']
|
{ text: 'Delaware', disabled: true },
|
||||||
}
|
{ text: 'Florida' },
|
||||||
|
{ text: 'Georqia' }
|
||||||
|
],
|
||||||
|
column3: {
|
||||||
|
Group1: ['Delaware', 'Florida', 'Georqia', 'Indiana', 'Maine'],
|
||||||
|
Group2: ['Alabama', 'Kansas', 'Louisiana', 'Texas']
|
||||||
|
},
|
||||||
|
toastContent: (value, index) => `Value: ${value}, Index:${index}`
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
columns() {
|
columns() {
|
||||||
const column = this.$t('column');
|
const column = this.$t('column3');
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
values: Object.keys(column),
|
values: Object.keys(column),
|
||||||
@ -48,27 +74,26 @@ export default {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
values: column[Object.keys(column)[0]],
|
values: column[Object.keys(column)[0]],
|
||||||
className: 'column2'
|
className: 'column2',
|
||||||
|
defaultIndex: 2
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
onChange(picker, values) {
|
onChange1(picker, value, index) {
|
||||||
picker.setColumnValues(1, this.$t('column')[values[0]]);
|
Toast(this.$t('toastContent', value, index));
|
||||||
|
},
|
||||||
|
onChange2(picker, values) {
|
||||||
|
picker.setColumnValues(1, this.$t('column3')[values[0]]);
|
||||||
|
},
|
||||||
|
onConfirm(value, index) {
|
||||||
|
Toast(this.$t('toastContent', value, index));
|
||||||
},
|
},
|
||||||
onCancel() {
|
onCancel() {
|
||||||
Toast('picker cancel');
|
Toast(this.$t('cancel'));
|
||||||
},
|
|
||||||
onConfirm() {
|
|
||||||
Toast('picker confirm');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
<style lang="postcss">
|
|
||||||
|
|
||||||
</style>
|
|
||||||
|
@ -42,13 +42,9 @@
|
|||||||
<!-- 自定义sku actions -->
|
<!-- 自定义sku actions -->
|
||||||
<template slot="sku-actions" slot-scope="props">
|
<template slot="sku-actions" slot-scope="props">
|
||||||
<div class="van-sku-actions">
|
<div class="van-sku-actions">
|
||||||
<button class="van-sku__add-cart-btn" @click="handlePointClicked">
|
<van-button bottomAction @click="handlePointClicked">积分兑换</van-button>
|
||||||
积分兑换
|
|
||||||
</button>
|
|
||||||
<!-- 直接触发sku内部事件,通过内部事件执行handleBuyClicked回调 -->
|
<!-- 直接触发sku内部事件,通过内部事件执行handleBuyClicked回调 -->
|
||||||
<button class="van-sku__buy-btn" @click="props.skuEventBus.$emit('sku:buy')">
|
<van-button type="primary" bottomAction @click="props.skuEventBus.$emit('sku:buy')">买买买</van-button>
|
||||||
买买买
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</van-sku>
|
</van-sku>
|
||||||
|
@ -11,55 +11,79 @@ Vue.component(Picker.name, Picker);
|
|||||||
|
|
||||||
#### Basic Usage
|
#### Basic Usage
|
||||||
|
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<van-picker :columns="pickerColumns" @change="onChange" />
|
<van-picker :columns="columns" @change="onChange" />
|
||||||
```
|
```
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
const states = {
|
|
||||||
'Group1': ['Delaware', 'Florida', 'Georqia', 'Indiana', 'Maine'],
|
|
||||||
'Group2': ['Alabama', 'Kansas', 'Louisiana', 'Texas']
|
|
||||||
};
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
pickerColumns: [
|
columns: ['Delaware', 'Florida', 'Georqia', 'Indiana', 'Maine']
|
||||||
{
|
|
||||||
values: Object.keys(states),
|
|
||||||
className: 'column1'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
values: states.Group1,
|
|
||||||
className: 'column2'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
onChange(picker, value, index) {
|
||||||
methods: {
|
Toast(`Value: ${value}, Index: ${index}`);
|
||||||
onChange(picker, values) {
|
|
||||||
picker.setColumnValues(1, citys[values[0]]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Disable option
|
||||||
|
|
||||||
#### Picker with toolbar
|
```html
|
||||||
|
<van-picker :columns="columns" />
|
||||||
|
```
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
columns: [
|
||||||
|
{ text: 'Delaware', disabled: true },
|
||||||
|
{ text: 'Florida' },
|
||||||
|
{ text: 'Georqia' }
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Show Toolbar
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<van-picker
|
<van-picker
|
||||||
showToolbar
|
showToolbar
|
||||||
:title="title"
|
:title="Title"
|
||||||
:columns="pickerColumns"
|
:columns="columns"
|
||||||
@change="onChange"
|
|
||||||
@cancel="onCancel"
|
@cancel="onCancel"
|
||||||
@confirm="onConfirm"
|
@confirm="onConfirm"
|
||||||
/>
|
/>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
columns: ['Delaware', 'Florida', 'Georqia', 'Indiana', 'Maine']
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onConfirm(value, index) {
|
||||||
|
Toast(`Value: ${value}, Index: ${index}`);
|
||||||
|
},
|
||||||
|
onCancel() {
|
||||||
|
Toast('Cancel');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Multi columns
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-picker :columns="columns" @change="onChange" />
|
||||||
|
```
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
const states = {
|
const states = {
|
||||||
'Group1': ['Delaware', 'Florida', 'Georqia', 'Indiana', 'Maine'],
|
'Group1': ['Delaware', 'Florida', 'Georqia', 'Indiana', 'Maine'],
|
||||||
@ -69,29 +93,22 @@ const states = {
|
|||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
title: 'Title',
|
columns: [
|
||||||
pickerColumns: [
|
|
||||||
{
|
{
|
||||||
values: Object.keys(states),
|
values: Object.keys(states),
|
||||||
className: 'column1'
|
className: 'column1'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
values: states.Group1,
|
values: states.Group1,
|
||||||
className: 'column2'
|
className: 'column2',
|
||||||
|
defaultIndex: 2
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
onChange(picker, values) {
|
onChange(picker, values) {
|
||||||
picker.setColumnValues(1, citys[values[0]]);
|
picker.setColumnValues(1, states[values[0]]);
|
||||||
},
|
|
||||||
onCancel() {
|
|
||||||
Toast('Cancel');
|
|
||||||
},
|
|
||||||
onConfirm() {
|
|
||||||
Toast('Confirm');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -101,11 +118,12 @@ export default {
|
|||||||
|
|
||||||
| Attribute | Description | Type | Default | Accepted Values |
|
| Attribute | Description | Type | Default | Accepted Values |
|
||||||
|-----------|-----------|-----------|-------------|-------------|
|
|-----------|-----------|-----------|-------------|-------------|
|
||||||
| visibileColumnCount | Count of columns to show | `Number` | `5` | - |
|
| columns | Columns data | `Array` | `[]` | - |
|
||||||
| itemHeight | Item height | `Number` | `44` | - |
|
| showToolbar | Whether to show toolbar | `Boolean` | `false` | - |
|
||||||
| columns | Columns data | `Array` | - | - |
|
| title | Toolbar title | `String` | `''` | - |
|
||||||
| showToolbar | Whether to show toolbar | `Boolean` | `true` | - |
|
| itemHeight | Option height | `Number` | `44` | - |
|
||||||
| title | Toolbar title | `String` | - | - |
|
| visibileColumnCount | Count of visible columns | `Number` | `5` | - |
|
||||||
|
| valueKey | Key of option text | `String` | `text` | - |
|
||||||
|
|
||||||
### Data struct of columns
|
### Data struct of columns
|
||||||
|
|
||||||
@ -116,13 +134,17 @@ export default {
|
|||||||
| className | ClassName for this column |
|
| className | ClassName for this column |
|
||||||
|
|
||||||
### Picker instance
|
### Picker instance
|
||||||
The first argument of change event's callback function is a picker instance with some methods
|
You can get the picker instance in 'change' event, and
|
||||||
|
|
||||||
| Method | Description |
|
| Method | Description |
|
||||||
|-----------|-----------|
|
|-----------|-----------|
|
||||||
| getColumnValue(index) | get current value of the column |
|
| getValues() | Get current values of all columns |
|
||||||
| setColumnValue(index, value) | set current value of the column |
|
| setValues(values) | Set current values of all columns |
|
||||||
| getColumnValues(index) | get all values of the column |
|
| getIndexes() | Get current indexes of all columns |
|
||||||
| setColumnValues(index, values) | set all values of the column |
|
| setIndexes(indexes) | Set current indexes of all columns |
|
||||||
| getValues() | get current values of all columns |
|
| getColumnValue(columnIndex) | Get current value of the column |
|
||||||
| setValues(values) | set current values of all columns |
|
| setColumnValue(columnIndex, value) | Set current value of the column |
|
||||||
|
| getColumnIndex(columnIndex) | Get current index of the column |
|
||||||
|
| setColumnIndex(columnIndex, optionIndex) | Set current index of the column |
|
||||||
|
| getColumnValues(columnIndex) | Get columns data of the column |
|
||||||
|
| setColumnValues(columnIndex, values) | Set columns data of the column |
|
||||||
|
@ -44,7 +44,7 @@ Use `position` prop to set popup display position
|
|||||||
| lockOnScroll | Lock body scroll | `Boolean` | `false` | - |
|
| lockOnScroll | Lock body scroll | `Boolean` | `false` | - |
|
||||||
| position | Position | `String` | - | `top` `bottom` `right` `left` |
|
| position | Position | `String` | - | `top` `bottom` `right` `left` |
|
||||||
| overlayClass | Custom overlay class | `String` | `` | - |
|
| overlayClass | Custom overlay class | `String` | `` | - |
|
||||||
| overlayStyle | Custom overlay style | `Object` | `` | - |
|
| overlayStyle | Custom overlay style | `Object` | - | - |
|
||||||
| closeOnClickOverlay | Close popup when click overlay | `Boolean` | `true` | - |
|
| closeOnClickOverlay | Close popup when click overlay | `Boolean` | `true` | - |
|
||||||
| transition | Transition | `String` | `popup-slide` | - |
|
| transition | Transition | `String` | `popup-slide` | - |
|
||||||
| preventScroll | Prevent background scroll | `Boolean` | `false` | - |
|
| preventScroll | Prevent background scroll | `Boolean` | `false` | - |
|
||||||
|
@ -49,13 +49,9 @@ Vue.component(Sku.name, Sku);
|
|||||||
<!-- 自定义sku actions -->
|
<!-- 自定义sku actions -->
|
||||||
<template slot="sku-actions" slot-scope="props">
|
<template slot="sku-actions" slot-scope="props">
|
||||||
<div class="van-sku-actions">
|
<div class="van-sku-actions">
|
||||||
<button class="van-sku__add-cart-btn" @click="handlePointClicked">
|
<van-button bottomAction @click="handlePointClicked">积分兑换</van-button>
|
||||||
积分兑换
|
|
||||||
</button>
|
|
||||||
<!-- 直接触发sku内部事件,通过内部事件执行handleBuyClicked回调 -->
|
<!-- 直接触发sku内部事件,通过内部事件执行handleBuyClicked回调 -->
|
||||||
<button class="van-sku__buy-btn" @click="props.skuEventBus.$emit('sku:buy')">
|
<van-button type="primary" bottomAction @click="props.skuEventBus.$emit('sku:buy')">买买买</van-button>
|
||||||
买买买
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</van-sku>
|
</van-sku>
|
||||||
|
@ -58,14 +58,14 @@ Vue.component(Button.name, Button);
|
|||||||
#### 页面底部操作按钮
|
#### 页面底部操作按钮
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<van-button type="primary" bottom-action>按钮</van-button>
|
<van-button type="primary" bottomAction>按钮</van-button>
|
||||||
|
|
||||||
<van-row>
|
<van-row>
|
||||||
<van-col span="12">
|
<van-col span="12">
|
||||||
<van-button bottom-action>按钮</van-button>
|
<van-button bottomAction>按钮</van-button>
|
||||||
</van-col>
|
</van-col>
|
||||||
<van-col span="12">
|
<van-col span="12">
|
||||||
<van-button type="primary" bottom-action>按钮</van-button>
|
<van-button type="primary" bottomAction>按钮</van-button>
|
||||||
</van-col>
|
</van-col>
|
||||||
</van-row>
|
</van-row>
|
||||||
```
|
```
|
||||||
|
@ -9,87 +9,108 @@ Vue.component(Picker.name, Picker);
|
|||||||
|
|
||||||
### 代码演示
|
### 代码演示
|
||||||
|
|
||||||
|
|
||||||
#### 基础用法
|
#### 基础用法
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<van-picker :columns="pickerColumns" @change="onChange" />
|
<van-picker :columns="columns" @change="onChange" />
|
||||||
```
|
```
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
const citys = {
|
|
||||||
'浙江': ['杭州', '宁波', '温州', '嘉兴', '湖州', '绍兴', '金华', '衢州'],
|
|
||||||
'福建': ['福州', '厦门', '莆田', '三明', '泉州', '漳州', '南平', '龙岩']
|
|
||||||
};
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
pickerColumns: [
|
columns: ['杭州', '宁波', '温州', '嘉兴', '湖州']
|
||||||
{
|
|
||||||
values: Object.keys(citys),
|
|
||||||
className: 'column1'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
values: citys['浙江'],
|
|
||||||
className: 'column2'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
onChange(picker, value, index) {
|
||||||
methods: {
|
Toast(`当前值:${value}, 当前索引:${index}`);
|
||||||
onChange(picker, values) {
|
|
||||||
picker.setColumnValues(1, citys[values[0]]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 带 toolbar 的 Picker
|
#### 禁用选项
|
||||||
|
选项可以为对象结构,通过设置 disabled 来禁用该选项
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-picker :columns="columns" />
|
||||||
|
```
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
columns: [
|
||||||
|
{ text: '杭州', disabled: true },
|
||||||
|
{ text: '宁波' },
|
||||||
|
{ text: '温州' }
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 展示顶部栏
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<van-picker
|
<van-picker
|
||||||
showToolbar
|
showToolbar
|
||||||
:title="title"
|
:title="标题"
|
||||||
:columns="pickerColumns"
|
:columns="columns"
|
||||||
@change="onChange"
|
|
||||||
@cancel="onCancel"
|
@cancel="onCancel"
|
||||||
@confirm="onConfirm"
|
@confirm="onConfirm"
|
||||||
/>
|
/>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
columns: ['杭州', '宁波', '温州', '嘉兴', '湖州']
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onConfirm(value, index) {
|
||||||
|
Toast(`当前值:${value}, 当前索引:${index}`);
|
||||||
|
},
|
||||||
|
onCancel() {
|
||||||
|
Toast('取消');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 多列联动
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-picker :columns="columns" @change="onChange" />
|
||||||
|
```
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
const citys = {
|
const citys = {
|
||||||
'浙江': ['杭州', '宁波', '温州', '嘉兴', '湖州', '绍兴', '金华', '衢州'],
|
'浙江': ['杭州', '宁波', '温州', '嘉兴', '湖州'],
|
||||||
'福建': ['福州', '厦门', '莆田', '三明', '泉州', '漳州', '南平', '龙岩']
|
'福建': ['福州', '厦门', '莆田', '三明', '泉州']
|
||||||
};
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
title: '地区选择',
|
columns: [
|
||||||
pickerColumns: [
|
|
||||||
{
|
{
|
||||||
values: Object.keys(citys),
|
values: Object.keys(citys),
|
||||||
className: 'column1'
|
className: 'column1'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
values: citys['浙江'],
|
values: citys['浙江'],
|
||||||
className: 'column2'
|
className: 'column2',
|
||||||
|
defaultIndex: 2
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
onChange(picker, values) {
|
onChange(picker, values) {
|
||||||
picker.setColumnValues(1, citys[values[0]]);
|
picker.setColumnValues(1, citys[values[0]]);
|
||||||
},
|
|
||||||
onCancel() {
|
|
||||||
Toast('picker cancel');
|
|
||||||
},
|
|
||||||
onConfirm() {
|
|
||||||
Toast('picker confirm');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -99,31 +120,34 @@ export default {
|
|||||||
|
|
||||||
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|
||||||
|-----------|-----------|-----------|-------------|-------------|
|
|-----------|-----------|-----------|-------------|-------------|
|
||||||
| visibileColumnCount | 每一列可见备选元素的个数 | `Number` | `5` | - |
|
| columns | 对象数组,配置每一列显示的数据 | `Array` | `[]` | - |
|
||||||
| itemHeight | 选中元素区高度 | `Number` | `44` | - |
|
| showToolbar | 是否显示顶部栏 | `Boolean` | `false` | - |
|
||||||
| columns | 对象数组,配置每一列显示的数据 | `Array` | - | - |
|
| title | 顶部栏标题 | `String` | `''` | - |
|
||||||
| showToolbar | 是否在组件顶部显示一个toolbar | `Boolean` | `true` | - |
|
| itemHeight | 选项高度 | `Number` | `44` | - |
|
||||||
| title | 在toolbar上显示的标题文字 | `String` | - | - |
|
| visibileColumnCount | 可见的选项个数 | `Number` | `5` | - |
|
||||||
|
| valueKey | 选项对象中,文字对应的 key | `String` | `text` | - |
|
||||||
|
|
||||||
### columns
|
### Columns 数据结构
|
||||||
|
当传入多列数据时,`columns`为一个对象数组,数组中的每一个对象配置每一列,每一列有以下`key`
|
||||||
`API`中的`columns`为一个对象数组,数组中的每一个对象配置每一列,每一列有以下`key`:
|
|
||||||
|
|
||||||
| key | 说明 |
|
| key | 说明 |
|
||||||
|-----------|-----------|
|
|-----------|-----------|
|
||||||
| values | 列中对应的备选值 |
|
| values | 列中对应的备选值 |
|
||||||
| defaultIndex | 初始选中值的索引,默认为0 |
|
| defaultIndex | 初始选中项的索引,默认为 0 |
|
||||||
| className | 为对应列添加特殊的`class` |
|
| className | 为对应列添加额外的`class` |
|
||||||
|
|
||||||
### change事件
|
### Picker 实例
|
||||||
|
在`change`事件中,可以获取到`picker`实例,通过实例方法可以灵活控制 Picker 内容
|
||||||
在`change`事件中,可以获取到`picker`实例,对`picker`进行相应的更新等操作:
|
|
||||||
|
|
||||||
| 函数 | 说明 |
|
| 函数 | 说明 |
|
||||||
|-----------|-----------|
|
|-----------|-----------|
|
||||||
| getColumnValue(index) | 获取对应列中选中的值 |
|
| getValues() | 获取所有列选中的值,返回一个数组 |
|
||||||
| setColumnValue(index, value) | 设置对应列中选中的值 |
|
| setValues(values) | 设置所有列选中的值 |
|
||||||
| getColumnValues(index) | 获取对应列中所有的备选值 |
|
| getIndexes() | 获取所有列选中值对应的索引,返回一个数组 |
|
||||||
| setColumnValues(index, values) | 设置对应列中所有的备选值 |
|
| setIndexes(indexes) | 设置所有列选中值对应的索引 |
|
||||||
| getValues() | 获取所有列中被选中的值,返回一个数组 |
|
| getColumnValue(columnIndex) | 获取对应列选中的值 |
|
||||||
| setValues(values) | `values`为一个数组,设置所有列中被选中的值 |
|
| setColumnValue(columnIndex, value) | 设置对应列选中的值 |
|
||||||
|
| getColumnIndex(columnIndex) | 获取对应列选中项的索引 |
|
||||||
|
| setColumnIndex(columnIndex, optionIndex) | 设置对应列选中项的索引 |
|
||||||
|
| getColumnValues(columnIndex) | 获取对应列中所有选项 |
|
||||||
|
| setColumnValues(columnIndex, values) | 设置对应列中所有选项 |
|
||||||
|
@ -49,13 +49,9 @@ Vue.component(Sku.name, Sku);
|
|||||||
<!-- 自定义sku actions -->
|
<!-- 自定义sku actions -->
|
||||||
<template slot="sku-actions" slot-scope="props">
|
<template slot="sku-actions" slot-scope="props">
|
||||||
<div class="van-sku-actions">
|
<div class="van-sku-actions">
|
||||||
<button class="van-sku__add-cart-btn" @click="handlePointClicked">
|
<van-button bottomAction @click="handlePointClicked">积分兑换</van-button>
|
||||||
积分兑换
|
|
||||||
</button>
|
|
||||||
<!-- 直接触发sku内部事件,通过内部事件执行handleBuyClicked回调 -->
|
<!-- 直接触发sku内部事件,通过内部事件执行handleBuyClicked回调 -->
|
||||||
<button class="van-sku__buy-btn" @click="props.skuEventBus.$emit('sku:buy')">
|
<van-button type="primary" bottomAction @click="props.skuEventBus.$emit('sku:buy')">买买买</van-button>
|
||||||
买买买
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</van-sku>
|
</van-sku>
|
||||||
|
@ -58,7 +58,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="postcss">
|
<style lang="postcss">
|
||||||
@import '../../../packages/vant-css/src/common/var';
|
@import '../../../packages/vant-css/src/common/var.css';
|
||||||
|
|
||||||
.side-nav {
|
.side-nav {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -51,7 +51,7 @@
|
|||||||
"vue": ">= 2.5.0"
|
"vue": ">= 2.5.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"autoprefixer": "^7.1.6",
|
"autoprefixer": "^7.2.1",
|
||||||
"avoriaz": "2.0.0",
|
"avoriaz": "2.0.0",
|
||||||
"babel-cli": "^6.26.0",
|
"babel-cli": "^6.26.0",
|
||||||
"babel-core": "^6.26.0",
|
"babel-core": "^6.26.0",
|
||||||
@ -63,6 +63,7 @@
|
|||||||
"babel-plugin-transform-vue-jsx": "^3.5.0",
|
"babel-plugin-transform-vue-jsx": "^3.5.0",
|
||||||
"babel-polyfill": "^6.26.0",
|
"babel-polyfill": "^6.26.0",
|
||||||
"babel-preset-env": "^1.6.1",
|
"babel-preset-env": "^1.6.1",
|
||||||
|
"cache-loader": "^1.2.0",
|
||||||
"chai": "^4.1.2",
|
"chai": "^4.1.2",
|
||||||
"cheerio": "^0.22.0",
|
"cheerio": "^0.22.0",
|
||||||
"codecov": "^3.0.0",
|
"codecov": "^3.0.0",
|
||||||
@ -70,7 +71,7 @@
|
|||||||
"css-loader": "^0.28.7",
|
"css-loader": "^0.28.7",
|
||||||
"dependency-tree": "^5.12.0",
|
"dependency-tree": "^5.12.0",
|
||||||
"eslint-plugin-vue": "^2.1.0",
|
"eslint-plugin-vue": "^2.1.0",
|
||||||
"extract-text-webpack-plugin": "2.0.0",
|
"extract-text-webpack-plugin": "3.0.2",
|
||||||
"fast-vue-md-loader": "^1.0.2",
|
"fast-vue-md-loader": "^1.0.2",
|
||||||
"felint": "^0.5.0-alpha.3",
|
"felint": "^0.5.0-alpha.3",
|
||||||
"file-save": "^0.2.0",
|
"file-save": "^0.2.0",
|
||||||
@ -115,7 +116,7 @@
|
|||||||
"vue-style-loader": "^3.0.0",
|
"vue-style-loader": "^3.0.0",
|
||||||
"vue-template-compiler": "^2.5.9",
|
"vue-template-compiler": "^2.5.9",
|
||||||
"vue-template-es2015-compiler": "^1.6.0",
|
"vue-template-es2015-compiler": "^1.6.0",
|
||||||
"webpack": "^3.8.1",
|
"webpack": "^3.9.1",
|
||||||
"webpack-bundle-analyzer": "^2.9.1",
|
"webpack-bundle-analyzer": "^2.9.1",
|
||||||
"webpack-dev-server": "^2.9.4",
|
"webpack-dev-server": "^2.9.4",
|
||||||
"webpack-merge": "^4.1.1"
|
"webpack-merge": "^4.1.1"
|
||||||
|
@ -59,6 +59,7 @@ export default {
|
|||||||
|
|
||||||
const columns = [];
|
const columns = [];
|
||||||
const curValue = this.value || '';
|
const curValue = this.value || '';
|
||||||
|
const { columnsNum } = this;
|
||||||
|
|
||||||
columns.push({
|
columns.push({
|
||||||
values: [DEFAULT_PROVINCE].concat(this.computedAreaList(PROVINCE_TYPE)),
|
values: [DEFAULT_PROVINCE].concat(this.computedAreaList(PROVINCE_TYPE)),
|
||||||
@ -66,7 +67,6 @@ export default {
|
|||||||
defaultIndex: this.getAreaIndex(PROVINCE_TYPE, curValue)
|
defaultIndex: this.getAreaIndex(PROVINCE_TYPE, curValue)
|
||||||
});
|
});
|
||||||
|
|
||||||
const columnsNum = this.columnsNum;
|
|
||||||
if (+columnsNum > 1) {
|
if (+columnsNum > 1) {
|
||||||
columns.push({
|
columns.push({
|
||||||
values: [DEFAULT_CITY].concat(this.computedAreaList(CITY_TYPE, curValue.slice(0, 2))),
|
values: [DEFAULT_CITY].concat(this.computedAreaList(CITY_TYPE, curValue.slice(0, 2))),
|
||||||
|
@ -225,7 +225,7 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
onChange(picker) {
|
onChange(picker) {
|
||||||
const values = picker.$children.filter(child => child.currentValue !== undefined).map(child => child.currentValue);
|
const values = picker.getValues();
|
||||||
let value;
|
let value;
|
||||||
|
|
||||||
if (this.type === 'time') {
|
if (this.type === 'time') {
|
||||||
@ -279,20 +279,7 @@ export default {
|
|||||||
if (!this.$refs.picker) {
|
if (!this.$refs.picker) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const setColumnValue = this.$refs.picker.setColumnValue;
|
this.$refs.picker.setValues(values);
|
||||||
if (this.type === 'time') {
|
|
||||||
setColumnValue(0, values[0]);
|
|
||||||
setColumnValue(1, values[1]);
|
|
||||||
} else {
|
|
||||||
setColumnValue(0, values[0]);
|
|
||||||
setColumnValue(1, values[1]);
|
|
||||||
setColumnValue(2, values[2]);
|
|
||||||
if (this.type === 'datetime') {
|
|
||||||
setColumnValue(3, values[3]);
|
|
||||||
setColumnValue(4, values[4]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
[].forEach.call(this.$refs.picker.$children, child => child.doOnValueChange());
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -3,41 +3,24 @@ import context from './popup-context';
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
// popup 当前显示状态
|
// whether to show popup
|
||||||
value: {
|
value: Boolean,
|
||||||
type: Boolean,
|
// whether to show overlay
|
||||||
default: false
|
overlay: Boolean,
|
||||||
},
|
// overlay custom style
|
||||||
// 是否显示遮罩层
|
overlayStyle: Object,
|
||||||
overlay: {
|
// overlay custom class name
|
||||||
type: Boolean,
|
overlayClass: String,
|
||||||
default: false
|
// whether to close popup when click overlay
|
||||||
},
|
closeOnClickOverlay: Boolean,
|
||||||
// 点击遮罩层是否关闭 popup
|
// z-index
|
||||||
closeOnClickOverlay: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
zIndex: [String, Number],
|
zIndex: [String, Number],
|
||||||
// popup 滚动时是否禁用 body 滚动
|
// prevent touchmove scroll
|
||||||
|
preventScroll: Boolean,
|
||||||
|
// prevent body scroll
|
||||||
lockOnScroll: {
|
lockOnScroll: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true
|
default: true
|
||||||
},
|
|
||||||
// 防止滚动穿透
|
|
||||||
preventScroll: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
// 遮罩层额外样式
|
|
||||||
overlayStyle: {
|
|
||||||
type: String,
|
|
||||||
default: ''
|
|
||||||
},
|
|
||||||
// 遮罩层额外类
|
|
||||||
overlayClass: {
|
|
||||||
type: String,
|
|
||||||
default: ''
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -1,245 +1,178 @@
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="van-picker-column" :class="classNames">
|
<div class="van-picker-column" :class="className">
|
||||||
<div class="van-picker-column-wrapper" :class="{ dragging: isDragging }" ref="wrapper" :style="{ height: visibleContentHeight + 'px' }">
|
<div class="van-picker-column__frame van-hairline--top-bottom" :style="frameStyle" />
|
||||||
<div
|
<ul
|
||||||
v-for="(item, index) in currentValues"
|
:style="wrapperStyle"
|
||||||
:key="index"
|
@touchstart="onTouchStart"
|
||||||
class="van-picker-column__item"
|
@touchmove.prevent="onTouchMove"
|
||||||
:class="{ 'van-picker-column__item--selected': item === currentValue }"
|
@touchend="onTouchEnd"
|
||||||
:style="{ height: itemHeight + 'px', lineHeight: itemHeight + 'px' }">
|
@touchcancel="onTouchEnd"
|
||||||
{{ typeof item === 'object' && item[valueKey] ? item[valueKey] : item }}
|
>
|
||||||
</div>
|
<li
|
||||||
</div>
|
v-for="(option, index) in options"
|
||||||
|
v-text="getOptionText(option)"
|
||||||
|
:class="{
|
||||||
|
'van-picker-column--disabled': isDisabled(option),
|
||||||
|
'van-picker-column--selected': index === currentIndex
|
||||||
|
}"
|
||||||
|
@click="setIndex(index)"
|
||||||
|
/>
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import translateUtil from '../utils/transition';
|
const DEFAULT_DURATION = 200;
|
||||||
import draggable from './draggable';
|
const range = (num, arr) => Math.min(Math.max(num, arr[0]), arr[1]);
|
||||||
|
|
||||||
const DEFAULT_ITEM_HEIGHT = 44;
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'van-picker-column',
|
name: 'van-picker-column',
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
/**
|
valueKey: String,
|
||||||
* 每一列可见备选元素的个数
|
className: String,
|
||||||
*/
|
options: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
},
|
||||||
|
itemHeight: {
|
||||||
|
type: Number,
|
||||||
|
default: 44
|
||||||
|
},
|
||||||
visibileColumnCount: {
|
visibileColumnCount: {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: 5
|
default: 5
|
||||||
},
|
},
|
||||||
/**
|
defaultIndex: {
|
||||||
* 该列所有的可选值
|
|
||||||
*/
|
|
||||||
values: {
|
|
||||||
type: Array,
|
|
||||||
default() {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 每列添加额外的`className`
|
|
||||||
*/
|
|
||||||
className: {
|
|
||||||
type: String,
|
|
||||||
default: ''
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 行高
|
|
||||||
*/
|
|
||||||
itemHeight: {
|
|
||||||
type: Number,
|
type: Number,
|
||||||
default: DEFAULT_ITEM_HEIGHT
|
default: 0
|
||||||
},
|
}
|
||||||
value: {},
|
|
||||||
valueKey: String
|
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
currentValue: this.value,
|
startY: 0,
|
||||||
currentValues: this.values,
|
offset: 0,
|
||||||
isDragging: false
|
duration: 0,
|
||||||
|
startOffset: 0,
|
||||||
|
currentIndex: this.defaultIndex
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
watch: {
|
created() {
|
||||||
values(val) {
|
this.$parent && this.$parent.children.push(this);
|
||||||
this.currentValues = val;
|
|
||||||
},
|
},
|
||||||
currentValues(val) {
|
|
||||||
/* istanbul ignore else */
|
mounted() {
|
||||||
if (this.valueIndex === -1) {
|
this.setIndex(this.currentIndex);
|
||||||
this.currentValue = (val || [])[0];
|
},
|
||||||
|
|
||||||
|
destroyed() {
|
||||||
|
this.$parent && this.$parent.children.splice(this.$parent.children.indexOf(this), 1);
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
defaultIndex() {
|
||||||
|
this.setIndex(this.defaultIndex);
|
||||||
|
},
|
||||||
|
|
||||||
|
options(next, prev) {
|
||||||
|
if (JSON.stringify(next) !== JSON.stringify(prev)) {
|
||||||
|
this.setIndex(this.defaultIndex);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
value(val) {
|
|
||||||
this.currentValue = val;
|
|
||||||
},
|
|
||||||
currentValue(val) {
|
|
||||||
this.doOnValueChange();
|
|
||||||
|
|
||||||
this.$emit('input', val);
|
currentIndex(index) {
|
||||||
this.$emit('columnChange', this);
|
this.$emit('change', index);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
/**
|
count() {
|
||||||
* picker可见备选元素总高度
|
return this.options.length;
|
||||||
*/
|
|
||||||
visibleContentHeight() {
|
|
||||||
return this.itemHeight * this.visibileColumnCount;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
wrapperStyle() {
|
||||||
* 当前选中值在`values`中的索引
|
const { itemHeight, visibileColumnCount } = this;
|
||||||
*/
|
return {
|
||||||
valueIndex() {
|
transition: `${this.duration}ms`,
|
||||||
return this.currentValues.indexOf(this.currentValue);
|
transform: `translate3d(0, ${this.offset}px, 0)`,
|
||||||
|
lineHeight: itemHeight + 'px',
|
||||||
|
height: itemHeight * visibileColumnCount + 'px',
|
||||||
|
paddingTop: itemHeight * (visibileColumnCount - 1) / 2 + 'px'
|
||||||
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
frameStyle() {
|
||||||
* 计算picker的拖动范围
|
return {
|
||||||
*/
|
height: this.itemHeight + 'px'
|
||||||
dragRange() {
|
|
||||||
var values = this.currentValues;
|
|
||||||
var visibileColumnCount = this.visibileColumnCount;
|
|
||||||
var itemHeight = this.itemHeight;
|
|
||||||
|
|
||||||
return [-itemHeight * (values.length - Math.ceil(visibileColumnCount / 2)), itemHeight * Math.floor(visibileColumnCount / 2)];
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 计算`classNames`
|
|
||||||
*/
|
|
||||||
classNames() {
|
|
||||||
return this.className.split(' ');
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
mounted() {
|
currentValue() {
|
||||||
this.initEvents();
|
return this.options[this.currentIndex];
|
||||||
this.doOnValueChange();
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
/**
|
onTouchStart(event) {
|
||||||
* 将当前`value`值转换成需要垂直方向需要`translate`的值
|
this.startY = event.touches[0].clientY;
|
||||||
*/
|
this.startOffset = this.offset;
|
||||||
value2Translate(value) {
|
this.duration = 0;
|
||||||
const values = this.currentValues;
|
},
|
||||||
const valueIndex = values.indexOf(value);
|
|
||||||
const offset = Math.floor(this.visibileColumnCount / 2);
|
|
||||||
const itemHeight = this.itemHeight;
|
|
||||||
|
|
||||||
if (valueIndex !== -1) {
|
onTouchMove(event) {
|
||||||
return (valueIndex - offset) * (-itemHeight);
|
const deltaY = event.touches[0].clientY - this.startY;
|
||||||
|
this.offset = range(this.startOffset + deltaY, [
|
||||||
|
-(this.count * this.itemHeight),
|
||||||
|
this.itemHeight
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
|
||||||
|
onTouchEnd() {
|
||||||
|
if (this.offset !== this.startOffset) {
|
||||||
|
this.duration = DEFAULT_DURATION;
|
||||||
|
const index = range(Math.round(-this.offset / this.itemHeight), [
|
||||||
|
0,
|
||||||
|
this.count - 1
|
||||||
|
]);
|
||||||
|
this.setIndex(index);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
adjustIndex(index) {
|
||||||
* 根据当前`translate`的值转换成当前选中的`value`
|
index = range(index, [0, this.count]);
|
||||||
*/
|
for (let i = index; i < this.count; i++) {
|
||||||
translate2Value(translate) {
|
if (!this.isDisabled(this.options[i])) return i;
|
||||||
const itemHeight = this.itemHeight;
|
}
|
||||||
translate = Math.round(translate / itemHeight) * itemHeight;
|
for (let i = index - 1; i >= 0; i--) {
|
||||||
|
if (!this.isDisabled(this.options[i])) return i;
|
||||||
const index = -(translate - Math.floor(this.visibileColumnCount / 2) * itemHeight) / itemHeight;
|
}
|
||||||
|
|
||||||
return this.currentValues[index];
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
isDisabled(option) {
|
||||||
* 初始化拖动事件
|
return typeof option === 'object' && option.disabled;
|
||||||
*/
|
|
||||||
initEvents() {
|
|
||||||
var el = this.$refs.wrapper;
|
|
||||||
var dragState = {};
|
|
||||||
|
|
||||||
var velocityTranslate;
|
|
||||||
var prevTranslate;
|
|
||||||
var pickerItems; // eslint-disable-line
|
|
||||||
|
|
||||||
draggable(el, {
|
|
||||||
start: (event) => {
|
|
||||||
// 存储当前状态
|
|
||||||
dragState = {
|
|
||||||
range: this.dragRange,
|
|
||||||
start: new Date(),
|
|
||||||
startLeft: event.pageX,
|
|
||||||
startTop: event.pageY,
|
|
||||||
startTranslateTop: translateUtil.getElementTranslate(el).top
|
|
||||||
};
|
|
||||||
|
|
||||||
pickerItems = el.querySelectorAll('.van-picker-item'); // eslint-disable-line
|
|
||||||
},
|
},
|
||||||
|
|
||||||
drag: (event) => {
|
getOptionText(option) {
|
||||||
this.isDragging = true;
|
return typeof option === 'object' && this.valueKey in option ? option[this.valueKey] : option;
|
||||||
|
|
||||||
dragState.left = event.pageX;
|
|
||||||
dragState.top = event.pageY;
|
|
||||||
|
|
||||||
const deltaY = dragState.top - dragState.startTop;
|
|
||||||
const translate = dragState.startTranslateTop + deltaY;
|
|
||||||
|
|
||||||
translateUtil.translateElement(el, null, translate);
|
|
||||||
|
|
||||||
velocityTranslate = translate - prevTranslate || translate;
|
|
||||||
|
|
||||||
prevTranslate = translate;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
end: () => {
|
setIndex(index) {
|
||||||
/* istanbul ignore else */
|
index = this.adjustIndex(index);
|
||||||
if (this.isDragging) {
|
this.offset = -index * this.itemHeight;
|
||||||
this.isDragging = false;
|
this.currentIndex = index;
|
||||||
|
|
||||||
var momentumRatio = 7;
|
|
||||||
var currentTranslate = translateUtil.getElementTranslate(el).top;
|
|
||||||
var duration = new Date() - dragState.start;
|
|
||||||
|
|
||||||
var momentumTranslate;
|
|
||||||
if (duration < 300) {
|
|
||||||
momentumTranslate = currentTranslate + velocityTranslate * momentumRatio;
|
|
||||||
}
|
|
||||||
|
|
||||||
var dragRange = dragState.range;
|
|
||||||
|
|
||||||
this.$nextTick(() => {
|
|
||||||
var translate;
|
|
||||||
var itemHeight = this.itemHeight;
|
|
||||||
|
|
||||||
if (momentumTranslate) {
|
|
||||||
translate = Math.round(momentumTranslate / itemHeight) * itemHeight;
|
|
||||||
} else {
|
|
||||||
translate = Math.round(currentTranslate / itemHeight) * itemHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
translate = Math.max(Math.min(translate, dragRange[1]), dragRange[0]);
|
|
||||||
|
|
||||||
translateUtil.translateElement(el, null, translate);
|
|
||||||
|
|
||||||
this.currentValue = this.translate2Value(translate);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
dragState = {};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
setValue(value) {
|
||||||
* `value`改变时调用
|
const { options, valueKey } = this;
|
||||||
*/
|
for (let i = 0; i < options.length; i++) {
|
||||||
doOnValueChange() {
|
if (this.getOptionText(options[i]) === value) {
|
||||||
const value = this.currentValue;
|
this.setIndex(i);
|
||||||
const wrapper = this.$refs.wrapper;
|
return;
|
||||||
|
}
|
||||||
translateUtil.translateElement(wrapper, null, this.value2Translate(value));
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,51 +0,0 @@
|
|||||||
import Vue from 'vue';
|
|
||||||
|
|
||||||
let isDragging = false;
|
|
||||||
|
|
||||||
const supportTouch = !Vue.prototype.$isServer && 'ontouchstart' in window;
|
|
||||||
|
|
||||||
export default function(element, options) {
|
|
||||||
const moveFn = function(event) {
|
|
||||||
if (options.drag) {
|
|
||||||
options.drag(supportTouch ? event.changedTouches[0] || event.touches[0] : event);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const endFn = function(event) {
|
|
||||||
if (!supportTouch) {
|
|
||||||
document.removeEventListener('mousemove', moveFn);
|
|
||||||
document.removeEventListener('mouseup', endFn);
|
|
||||||
}
|
|
||||||
document.onselectstart = null;
|
|
||||||
document.ondragstart = null;
|
|
||||||
|
|
||||||
isDragging = false;
|
|
||||||
|
|
||||||
if (options.end) {
|
|
||||||
options.end(supportTouch ? event.changedTouches[0] || event.touches[0] : event);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
element.addEventListener(supportTouch ? 'touchstart' : 'mousedown', function(event) {
|
|
||||||
if (isDragging) return;
|
|
||||||
document.onselectstart = function() { return false; };
|
|
||||||
document.ondragstart = function() { return false; };
|
|
||||||
|
|
||||||
if (!supportTouch) {
|
|
||||||
document.addEventListener('mousemove', moveFn);
|
|
||||||
document.addEventListener('mouseup', endFn);
|
|
||||||
}
|
|
||||||
isDragging = true;
|
|
||||||
|
|
||||||
if (options.start) {
|
|
||||||
event.preventDefault();
|
|
||||||
options.start(supportTouch ? event.changedTouches[0] || event.touches[0] : event);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (supportTouch) {
|
|
||||||
element.addEventListener('touchmove', moveFn);
|
|
||||||
element.addEventListener('touchend', endFn);
|
|
||||||
element.addEventListener('touchcancel', endFn);
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,34 +1,32 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="van-picker">
|
<div class="van-picker">
|
||||||
<div class="van-picker__toolbar van-hairline--top-bottom" v-show="showToolbar">
|
<div class="van-picker__toolbar van-hairline--top-bottom" v-if="showToolbar">
|
||||||
<slot>
|
<slot>
|
||||||
<a href="javascript:void(0)" class="van-picker__cancel" @click="handlePickerCancel">{{ $t('cancel') }}</a>
|
<div class="van-picker__cancel" @click="emit('cancel')">{{ $t('cancel') }}</div>
|
||||||
<a href="javascript:void(0)" class="van-picker__confirm" @click="handlePickerConfirm">{{ $t('confirm') }}</a>
|
<div class="van-picker__confirm" @click="emit('confirm')">{{ $t('confirm') }}</div>
|
||||||
<div v-if="title" class="van-picker__title">{{ title }}</div>
|
<div class="van-picker__title" v-if="title" v-text="title" />
|
||||||
</slot>
|
</slot>
|
||||||
</div>
|
</div>
|
||||||
<div class="van-picker__columns" :class="`van-picker__columns--${columns.length}`">
|
<div class="van-picker__columns">
|
||||||
<van-picker-column
|
<van-picker-column
|
||||||
v-for="(item, index) in columns"
|
v-for="(item, index) in currentColumns"
|
||||||
:key="index"
|
:key="index"
|
||||||
v-model="values[index]"
|
|
||||||
:values="item.values"
|
|
||||||
:className="item.className"
|
|
||||||
:itemHeight="itemHeight"
|
|
||||||
:visibleItemCount="visibileColumnCount"
|
|
||||||
:valueKey="valueKey"
|
:valueKey="valueKey"
|
||||||
@columnChange="columnValueChange(index)"
|
:options="item.values"
|
||||||
|
:className="item.className"
|
||||||
|
:defaultIndex="item.defaultIndex"
|
||||||
|
:itemHeight="itemHeight"
|
||||||
|
:visibileColumnCount="visibileColumnCount"
|
||||||
|
@change="onChange(index)"
|
||||||
/>
|
/>
|
||||||
<div class="van-picker-center-highlight" :style="{ height: itemHeight + 'px', marginTop: -itemHeight / 2 + 'px' }"></div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import PickerColumn from './PickerColumn';
|
|
||||||
import { i18n } from '../locale';
|
import { i18n } from '../locale';
|
||||||
|
import Column from './PickerColumn';
|
||||||
const DEFAULT_ITEM_HEIGHT = 44;
|
import deepClone from '../utils/deep-clone';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'van-picker',
|
name: 'van-picker',
|
||||||
@ -36,132 +34,126 @@ export default {
|
|||||||
mixins: [i18n],
|
mixins: [i18n],
|
||||||
|
|
||||||
components: {
|
components: {
|
||||||
[PickerColumn.name]: PickerColumn
|
[Column.name]: Column
|
||||||
},
|
},
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
/**
|
title: String,
|
||||||
* 每一列可见备选元素的个数
|
valueKey: {
|
||||||
*/
|
type: String,
|
||||||
visibileColumnCount: {
|
default: 'text'
|
||||||
type: Number,
|
|
||||||
default: 5
|
|
||||||
},
|
},
|
||||||
/**
|
itemHeight: Number,
|
||||||
* 选中元素区高度
|
showToolbar: Boolean,
|
||||||
*/
|
visibileColumnCount: Number,
|
||||||
itemHeight: {
|
|
||||||
type: Number,
|
|
||||||
default: DEFAULT_ITEM_HEIGHT
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 对象数组,配置每一列显示的数据
|
|
||||||
*/
|
|
||||||
columns: {
|
columns: {
|
||||||
type: Array,
|
type: Array,
|
||||||
default() {
|
default: () => []
|
||||||
return [];
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
/**
|
|
||||||
* 否在组件顶部显示一个toolbar
|
|
||||||
*/
|
|
||||||
showToolbar: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 顶部toolbar 显示的title
|
|
||||||
*/
|
|
||||||
title: String,
|
|
||||||
valueKey: String
|
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
data() {
|
||||||
values() {
|
return {
|
||||||
const columns = this.columns || [];
|
children: [],
|
||||||
const values = [];
|
currentColumns: []
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
columns.forEach(column => {
|
created() {
|
||||||
values.push(column.value || column.values[column.defaultIndex || 0]);
|
this.initColumns();
|
||||||
});
|
},
|
||||||
|
|
||||||
return values;
|
watch: {
|
||||||
}
|
columns() {
|
||||||
|
this.initColumns();
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
handlePickerCancel() {
|
initColumns() {
|
||||||
this.$emit('cancel', this.values);
|
const columns = this.columns.map(deepClone);
|
||||||
},
|
this.isSimpleColumn = columns.length && !columns[0].values;
|
||||||
handlePickerConfirm() {
|
this.currentColumns = this.isSimpleColumn ? [{ values: columns }] : columns;
|
||||||
this.$emit('confirm', this.values);
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 处理列`change`事件
|
|
||||||
*/
|
|
||||||
columnValueChange(index) {
|
|
||||||
this.$emit('change', this, this.values, index);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
emit(event) {
|
||||||
* 获取对应索引的列的实例
|
if (this.isSimpleColumn) {
|
||||||
*/
|
this.$emit(event, this.getColumnValue(0), this.getColumnIndex(0));
|
||||||
|
} else {
|
||||||
|
this.$emit(event, this.getValues(), this.getIndexes());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
onChange(columnIndex) {
|
||||||
|
if (this.isSimpleColumn) {
|
||||||
|
this.$emit('change', this, this.getColumnValue(0), this.getColumnIndex(0));
|
||||||
|
} else {
|
||||||
|
this.$emit('change', this, this.getValues(), columnIndex);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// get column instance by index
|
||||||
getColumn(index) {
|
getColumn(index) {
|
||||||
const children = this.$children.filter(child => child.$options.name === 'van-picker-column');
|
return this.children[index];
|
||||||
return children[index];
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
// get column value by index
|
||||||
* 获取对应列中选中的值
|
|
||||||
*/
|
|
||||||
getColumnValue(index) {
|
getColumnValue(index) {
|
||||||
const column = this.getColumn(index);
|
return (this.getColumn(index) || {}).currentValue;
|
||||||
return column && column.values[column.valueIndex];
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
// set column value by index
|
||||||
* 设置对应列中选中的值
|
|
||||||
*/
|
|
||||||
setColumnValue(index, value) {
|
setColumnValue(index, value) {
|
||||||
const column = this.getColumn(index);
|
const column = this.getColumn(index);
|
||||||
if (column) {
|
column && column.setValue(value);
|
||||||
column.currentValue = value;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
// get column option index by column index
|
||||||
* 获取对应列中所有的备选值
|
getColumnIndex(columnIndex) {
|
||||||
*/
|
return (this.getColumn(columnIndex) || {}).currentIndex;
|
||||||
|
},
|
||||||
|
|
||||||
|
// set column option index by column index
|
||||||
|
setColumnIndex(columnIndex, optionIndex) {
|
||||||
|
const column = this.getColumn(columnIndex);
|
||||||
|
column && column.setIndex(optionIndex);
|
||||||
|
},
|
||||||
|
|
||||||
|
// get options of column by index
|
||||||
getColumnValues(index) {
|
getColumnValues(index) {
|
||||||
const column = this.getColumn(index);
|
return (this.currentColumns[index] || {}).values;
|
||||||
return column && column.currentValues;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
// set options of column by index
|
||||||
* 设置对应列中所有的备选值
|
setColumnValues(index, options) {
|
||||||
*/
|
const column = this.currentColumns[index];
|
||||||
setColumnValues(index, values) {
|
|
||||||
const column = this.getColumn(index);
|
|
||||||
if (column) {
|
if (column) {
|
||||||
column.currentValues = values;
|
column.values = options;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
// get values of all columns
|
||||||
* 获取所有列中被选中的值,返回一个数组
|
|
||||||
*/
|
|
||||||
getValues() {
|
getValues() {
|
||||||
return this.values;
|
return this.children.map(child => child.currentValue);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
// set values of all columns
|
||||||
* `values`为一个数组,设置所有列中被选中的值
|
|
||||||
*/
|
|
||||||
setValues(values) {
|
setValues(values) {
|
||||||
values.forEach((value, index) => {
|
values.forEach((value, index) => {
|
||||||
this.setColumnValue(index, value);
|
this.setColumnValue(index, value);
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// get indexes of all columns
|
||||||
|
getIndexes() {
|
||||||
|
return this.children.map(child => child.currentIndex);
|
||||||
|
},
|
||||||
|
|
||||||
|
// set indexes of all columns
|
||||||
|
setIndexes(indexes) {
|
||||||
|
indexes.forEach((optionIndex, columnIndex) => {
|
||||||
|
this.setColumnIndex(columnIndex, optionIndex);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,18 +1,20 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="van-sku-actions">
|
<div class="van-sku-actions">
|
||||||
<button v-if="showAddCartBtn" class="van-sku__add-cart-btn" @click="onAddCartClicked">
|
<van-button v-if="showAddCartBtn" bottomAction @click="onAddCartClicked">加入购物车</van-button>
|
||||||
加入购物车
|
<van-button type="primary" bottomAction @click="onBuyClicked">{{ buyText }}</van-button>
|
||||||
</button>
|
|
||||||
<button class="van-sku__buy-btn" @click="onBuyClicked">
|
|
||||||
{{ buyText }}
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import Button from '../../button';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'van-sku-actions',
|
name: 'van-sku-actions',
|
||||||
|
|
||||||
|
components: {
|
||||||
|
[Button.name]: Button
|
||||||
|
},
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
skuEventBus: Object,
|
skuEventBus: Object,
|
||||||
showAddCartBtn: Boolean,
|
showAddCartBtn: Boolean,
|
||||||
|
10
packages/utils/deep-clone.js
Normal file
10
packages/utils/deep-clone.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import deepAssign from './deep-assign';
|
||||||
|
|
||||||
|
export default function deepClone(obj) {
|
||||||
|
if (Array.isArray(obj)) {
|
||||||
|
return obj.map(item => deepClone(item));
|
||||||
|
} else if (typeof obj === 'object') {
|
||||||
|
return deepAssign({}, obj);
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
}
|
@ -1,7 +1,9 @@
|
|||||||
@import './common/var.css';
|
@import './common/var.css';
|
||||||
|
@import './mixins/ellipsis.css';
|
||||||
|
|
||||||
.van-picker {
|
.van-picker {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
user-select: none;
|
||||||
background-color: $white;
|
background-color: $white;
|
||||||
|
|
||||||
&__toolbar {
|
&__toolbar {
|
||||||
@ -12,6 +14,7 @@
|
|||||||
|
|
||||||
&__cancel,
|
&__cancel,
|
||||||
&__confirm {
|
&__confirm {
|
||||||
|
color: $blue;
|
||||||
padding: 0 15px;
|
padding: 0 15px;
|
||||||
|
|
||||||
&:active {
|
&:active {
|
||||||
@ -20,132 +23,56 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&__cancel {
|
&__cancel {
|
||||||
color: $blue;
|
|
||||||
float: left;
|
float: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__confirm {
|
&__confirm {
|
||||||
color: $blue;
|
|
||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__title {
|
&__title {
|
||||||
height: 40px;
|
|
||||||
padding: 0 10px;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
word-wrap: normal;
|
|
||||||
word-break: break-all;
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
@mixin ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__columns {
|
&__columns {
|
||||||
|
display: flex;
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
|
||||||
|
|
||||||
&--1 {
|
|
||||||
.van-picker-column {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&--2 {
|
|
||||||
.van-picker-column {
|
|
||||||
width: 50%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&--3 {
|
|
||||||
.van-picker-column {
|
|
||||||
width: 33.333%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&--4 {
|
|
||||||
.van-picker-column {
|
|
||||||
width: 25%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&--5 {
|
|
||||||
.van-picker-column {
|
|
||||||
width: 20%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.van-picker-center-highlight {
|
|
||||||
box-sizing: border-box;
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
top: 50%;
|
|
||||||
margin-top: -18px;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.van-picker-center-highlight:before,
|
|
||||||
.van-picker-center-highlight:after {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
height: 1px;
|
|
||||||
width: 100%;
|
|
||||||
background-color: #eaeaea;
|
|
||||||
display: block;
|
|
||||||
transform: scaleY(0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
.van-picker-center-highlight:before {
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
bottom: auto;
|
|
||||||
right: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.van-picker-center-highlight:after {
|
|
||||||
left: 0;
|
|
||||||
bottom: 0;
|
|
||||||
right: auto;
|
|
||||||
top: auto;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&-column {
|
&-column {
|
||||||
font-size: 18px;
|
flex: 1;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
font-size: 18px;
|
||||||
position: relative;
|
position: relative;
|
||||||
max-height: 100%;
|
|
||||||
float: left;
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
&__item {
|
ul {
|
||||||
height: 44px;
|
|
||||||
line-height: 44px;
|
|
||||||
padding: 0 10px;
|
|
||||||
white-space: nowrap;
|
|
||||||
position: relative;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
color: #707274;
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
width: 100%;
|
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
transition-duration: .3s;
|
}
|
||||||
|
|
||||||
&--selected {
|
li {
|
||||||
|
padding: 0 10px;
|
||||||
|
color: $gray-darker;
|
||||||
|
@mixin ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
li&--selected {
|
||||||
color: $black;
|
color: $black;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
li&--disabled {
|
||||||
|
opacity: .3;
|
||||||
}
|
}
|
||||||
|
|
||||||
.picker-column-wrapper {
|
&__frame {
|
||||||
transition-duration: 0.3s;
|
top: 50%;
|
||||||
transition-timing-function: ease-out;
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
z-index: 1;
|
||||||
|
position: absolute;
|
||||||
|
pointer-events: none;
|
||||||
|
transform: translateY(-50%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.picker-column-wrapper.dragging,
|
|
||||||
.picker-column-wrapper.dragging .picker-item {
|
|
||||||
transition-duration: 0s;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -174,35 +174,7 @@
|
|||||||
|
|
||||||
/* sku actions */
|
/* sku actions */
|
||||||
&-actions {
|
&-actions {
|
||||||
|
display: flex;
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
font-size: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__add-cart-btn {
|
|
||||||
width: 50%;
|
|
||||||
height: 50px;
|
|
||||||
padding: 0;
|
|
||||||
border: 0;
|
|
||||||
background: #f85;
|
|
||||||
color: $white;
|
|
||||||
font-size: 16px;
|
|
||||||
line-height: 50px;
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
& + .van-sku__buy-btn {
|
|
||||||
width: 50%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__buy-btn {
|
|
||||||
width: 100%;
|
|
||||||
height: 50px;
|
|
||||||
padding: 0;
|
|
||||||
border: 0;
|
|
||||||
background: $red;
|
|
||||||
color: $white;
|
|
||||||
font-size: 16px;
|
|
||||||
line-height: 50px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import Area from 'packages/area';
|
import Area from 'packages/area';
|
||||||
import { mount } from 'avoriaz';
|
import { mount } from 'avoriaz';
|
||||||
import AreaList from '../mock/area.json';
|
import AreaList from '../mock/area.json';
|
||||||
|
import { setTimeout } from 'timers';
|
||||||
|
|
||||||
describe('Area', () => {
|
describe('Area', () => {
|
||||||
let wrapper;
|
let wrapper;
|
||||||
@ -54,10 +55,10 @@ describe('Area', () => {
|
|||||||
wrapper.setProps({
|
wrapper.setProps({
|
||||||
value: '110102'
|
value: '110102'
|
||||||
});
|
});
|
||||||
wrapper.vm.$nextTick(() => {
|
setTimeout(() => {
|
||||||
expect(wrapper.vm.$refs.picker.getColumnValue(2).code).to.equal('110102');
|
expect(wrapper.vm.$refs.picker.getColumnValue(2).code).to.equal('110102');
|
||||||
done();
|
done();
|
||||||
});
|
}, 50);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('create an area with invalid areaList', () => {
|
it('create an area with invalid areaList', () => {
|
||||||
|
@ -1,15 +1,6 @@
|
|||||||
import DatetimePicker from 'packages/datetime-picker';
|
import DatetimePicker from 'packages/datetime-picker';
|
||||||
import { mount } from 'avoriaz';
|
import { mount } from 'avoriaz';
|
||||||
import { triggerTouch } from '../utils';
|
import { dragHelper } from '../utils';
|
||||||
|
|
||||||
const dragHelper = (el, position) => {
|
|
||||||
triggerTouch(el, 'touchstart', 0, 0);
|
|
||||||
triggerTouch(el, 'touchmove', 0, position / 4);
|
|
||||||
triggerTouch(el, 'touchmove', 0, position / 3);
|
|
||||||
triggerTouch(el, 'touchmove', 0, position / 2);
|
|
||||||
triggerTouch(el, 'touchmove', 0, position);
|
|
||||||
triggerTouch(el, 'touchend', 0, position);
|
|
||||||
};
|
|
||||||
|
|
||||||
const testTime = '10:00';
|
const testTime = '10:00';
|
||||||
const testDate = new Date('2017/03/10 10:00');
|
const testDate = new Date('2017/03/10 10:00');
|
||||||
@ -64,12 +55,12 @@ describe('DatetimePicker', () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const [hour, minute] = wrapper.find('.van-picker-column-wrapper');
|
const [hour, minute] = wrapper.find('.van-picker-column ul');
|
||||||
dragHelper(hour, -50);
|
dragHelper(hour, -50);
|
||||||
dragHelper(minute, -50);
|
dragHelper(minute, -50);
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
expect(wrapper.vm.innerValue).to.equal('5:05');
|
expect(wrapper.vm.innerValue).to.equal('10:01');
|
||||||
done();
|
done();
|
||||||
}, 10);
|
}, 10);
|
||||||
});
|
});
|
||||||
@ -86,7 +77,7 @@ describe('DatetimePicker', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const [year, month, day] = wrapper.find('.van-picker-column-wrapper');
|
const [year, month, day] = wrapper.find('.van-picker-column ul');
|
||||||
dragHelper(year, -50);
|
dragHelper(year, -50);
|
||||||
dragHelper(month, -50);
|
dragHelper(month, -50);
|
||||||
dragHelper(day, -50);
|
dragHelper(day, -50);
|
||||||
@ -94,9 +85,9 @@ describe('DatetimePicker', () => {
|
|||||||
const newYear = wrapper.vm.innerValue.getFullYear();
|
const newYear = wrapper.vm.innerValue.getFullYear();
|
||||||
const newMonth = wrapper.vm.innerValue.getMonth() + 1;
|
const newMonth = wrapper.vm.innerValue.getMonth() + 1;
|
||||||
const newDay = wrapper.vm.innerValue.getDate();
|
const newDay = wrapper.vm.innerValue.getDate();
|
||||||
expect(newYear).to.equal(2022);
|
expect(newYear).to.equal(2018);
|
||||||
expect(newMonth).to.equal(8);
|
expect(newMonth).to.equal(4);
|
||||||
expect(newDay).to.equal(15);
|
expect(newDay).to.equal(1);
|
||||||
done();
|
done();
|
||||||
}, 10);
|
}, 10);
|
||||||
}, 10);
|
}, 10);
|
||||||
@ -114,7 +105,7 @@ describe('DatetimePicker', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const [year, month, day, hour, minute] = wrapper.find('.van-picker-column-wrapper');
|
const [year, month, day, hour, minute] = wrapper.find('.van-picker-column ul');
|
||||||
dragHelper(year, -50);
|
dragHelper(year, -50);
|
||||||
dragHelper(month, -50);
|
dragHelper(month, -50);
|
||||||
dragHelper(day, -50);
|
dragHelper(day, -50);
|
||||||
@ -126,11 +117,11 @@ describe('DatetimePicker', () => {
|
|||||||
const newDay = wrapper.vm.innerValue.getDate();
|
const newDay = wrapper.vm.innerValue.getDate();
|
||||||
const newHour = wrapper.vm.innerValue.getHours();
|
const newHour = wrapper.vm.innerValue.getHours();
|
||||||
const newMinute = wrapper.vm.innerValue.getMinutes();
|
const newMinute = wrapper.vm.innerValue.getMinutes();
|
||||||
expect(newYear).to.equal(2022);
|
expect(newYear).to.equal(2018);
|
||||||
expect(newMonth).to.equal(8);
|
expect(newMonth).to.equal(4);
|
||||||
expect(newDay).to.equal(15);
|
expect(newDay).to.equal(1);
|
||||||
expect(newHour).to.equal(15);
|
expect(newHour).to.equal(11);
|
||||||
expect(newMinute).to.equal(5);
|
expect(newMinute).to.equal(1);
|
||||||
done();
|
done();
|
||||||
}, 10);
|
}, 10);
|
||||||
}, 10);
|
}, 10);
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import Picker from 'packages/picker';
|
import Picker from 'packages/picker';
|
||||||
import PickerColumn from 'packages/picker/PickerColumn';
|
import PickerColumn from 'packages/picker/PickerColumn';
|
||||||
import { mount } from 'avoriaz';
|
import { mount } from 'avoriaz';
|
||||||
|
import { dragHelper } from '../utils';
|
||||||
const itemHeight = 44;
|
|
||||||
|
|
||||||
const pickerColumns = [
|
const pickerColumns = [
|
||||||
{
|
{
|
||||||
@ -29,7 +28,6 @@ describe('Picker', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
expect(wrapper.hasClass('van-picker')).to.be.true;
|
expect(wrapper.hasClass('van-picker')).to.be.true;
|
||||||
expect(wrapper.contains('.van-picker__columns--2')).to.be.true;
|
|
||||||
|
|
||||||
expect(wrapper.vm.getColumnValues(0).length).to.equal(2);
|
expect(wrapper.vm.getColumnValues(0).length).to.equal(2);
|
||||||
expect(wrapper.vm.getValues().length).to.equal(2);
|
expect(wrapper.vm.getValues().length).to.equal(2);
|
||||||
@ -42,7 +40,6 @@ describe('Picker', () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(wrapper.contains('.van-picker__columns--2')).to.be.true;
|
|
||||||
expect(wrapper.vm.getColumnValues(0).length).to.equal(2);
|
expect(wrapper.vm.getColumnValues(0).length).to.equal(2);
|
||||||
expect(wrapper.vm.getColumnValues(1).length).to.equal(6);
|
expect(wrapper.vm.getColumnValues(1).length).to.equal(6);
|
||||||
|
|
||||||
@ -52,16 +49,25 @@ describe('Picker', () => {
|
|||||||
wrapper.vm.setColumnValue(0, 'normal');
|
wrapper.vm.setColumnValue(0, 'normal');
|
||||||
expect(wrapper.vm.getColumnValue(0)).to.equal('normal');
|
expect(wrapper.vm.getColumnValue(0)).to.equal('normal');
|
||||||
|
|
||||||
|
wrapper.vm.setColumnIndex(0, 0);
|
||||||
|
expect(wrapper.vm.getColumnValue(0)).to.equal('vip');
|
||||||
|
|
||||||
wrapper.vm.setColumnValue(1, '1991');
|
wrapper.vm.setColumnValue(1, '1991');
|
||||||
expect(wrapper.vm.getColumnValue(1)).to.equal('1991');
|
expect(wrapper.vm.getColumnValue(1)).to.equal('1991');
|
||||||
|
|
||||||
wrapper.vm.setColumnValues(0, ['vip', 'normal', 'other']);
|
wrapper.vm.setColumnValues(0, ['vip', 'normal', 'other']);
|
||||||
expect(wrapper.vm.getColumnValues(0).length).to.equal(3);
|
expect(wrapper.vm.getColumnValues(0).length).to.equal(3);
|
||||||
|
|
||||||
expect(wrapper.vm.getValues().length).to.equal(2);
|
expect(wrapper.vm.getValues().length).to.equal(2);
|
||||||
|
|
||||||
wrapper.vm.setValues(['vip', '1992']);
|
wrapper.vm.setValues(['vip', '1992']);
|
||||||
expect(wrapper.vm.getColumnValue(0)).to.equal('vip');
|
expect(wrapper.vm.getColumnIndex(0)).to.equal(0);
|
||||||
expect(wrapper.vm.getColumnValue(1)).to.equal('1992');
|
expect(wrapper.vm.getColumnIndex(1)).to.equal(2);
|
||||||
|
expect(wrapper.vm.getColumnIndex(2)).to.equal(undefined);
|
||||||
|
|
||||||
|
wrapper.vm.setIndexes([1, 4]);
|
||||||
|
expect(wrapper.vm.getColumnValue(0)).to.equal('normal');
|
||||||
|
expect(wrapper.vm.getColumnValue(1)).to.equal('1994');
|
||||||
|
expect(wrapper.vm.getColumnValue(2)).to.equal(undefined);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('create a invalid columns picker', () => {
|
it('create a invalid columns picker', () => {
|
||||||
@ -72,7 +78,7 @@ describe('Picker', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
expect(wrapper.hasClass('van-picker')).to.be.true;
|
expect(wrapper.hasClass('van-picker')).to.be.true;
|
||||||
expect(wrapper.vm.values.length).to.equal(0);
|
expect(wrapper.vm.currentColumns.length).to.equal(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('set invalid index columns', () => {
|
it('set invalid index columns', () => {
|
||||||
@ -99,10 +105,7 @@ describe('Picker', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const eventStub = sinon.stub(wrapper.vm, '$emit');
|
const eventStub = sinon.stub(wrapper.vm, '$emit');
|
||||||
const firstColumn = wrapper.find(PickerColumn)[0];
|
wrapper.vm.setColumnValue(0, 'normal');
|
||||||
firstColumn.vm.currentValue = 'normal';
|
|
||||||
|
|
||||||
firstColumn.update();
|
|
||||||
wrapper.vm.$nextTick(() => {
|
wrapper.vm.$nextTick(() => {
|
||||||
expect(eventStub.calledOnce).to.be.true;
|
expect(eventStub.calledOnce).to.be.true;
|
||||||
expect(eventStub.calledWith('change'));
|
expect(eventStub.calledWith('change'));
|
||||||
@ -119,7 +122,7 @@ describe('Picker', () => {
|
|||||||
|
|
||||||
expect(wrapper.hasClass('van-picker')).to.be.true;
|
expect(wrapper.hasClass('van-picker')).to.be.true;
|
||||||
expect(wrapper.contains('.van-picker__toolbar')).to.be.true;
|
expect(wrapper.contains('.van-picker__toolbar')).to.be.true;
|
||||||
expect(wrapper.vm.values.length).to.equal(0);
|
expect(wrapper.vm.currentColumns.length).to.equal(0);
|
||||||
|
|
||||||
const eventStub = sinon.stub(wrapper.vm, '$emit');
|
const eventStub = sinon.stub(wrapper.vm, '$emit');
|
||||||
const cancelBtn = wrapper.find('.van-picker__cancel')[0];
|
const cancelBtn = wrapper.find('.van-picker__cancel')[0];
|
||||||
@ -164,25 +167,20 @@ describe('PickerColumn', () => {
|
|||||||
wrapper = mount(PickerColumn);
|
wrapper = mount(PickerColumn);
|
||||||
|
|
||||||
expect(wrapper.hasClass('van-picker-column')).to.be.true;
|
expect(wrapper.hasClass('van-picker-column')).to.be.true;
|
||||||
expect(wrapper.vm.values.length).to.equal(0);
|
expect(wrapper.vm.options.length).to.equal(0);
|
||||||
expect(wrapper.vm.visibleContentHeight).to.equal(itemHeight * 5);
|
|
||||||
expect(wrapper.vm.dragRange[0]).to.equal(3 * itemHeight);
|
|
||||||
expect(wrapper.vm.dragRange[1]).to.equal(2 * itemHeight);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('change picker-column value', (done) => {
|
it('change picker-column value', (done) => {
|
||||||
wrapper = mount(PickerColumn, {
|
wrapper = mount(PickerColumn, {
|
||||||
propsData: {
|
propsData: {
|
||||||
values: [1, 2, 3, 4, 5],
|
options: [1, 2, 3, 4, 5],
|
||||||
value: 1
|
value: 1
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(wrapper.hasClass('van-picker-column')).to.be.true;
|
expect(wrapper.vm.options.length).to.equal(5);
|
||||||
expect(wrapper.vm.values.length).to.equal(5);
|
|
||||||
|
|
||||||
wrapper.vm.value = 3;
|
wrapper.vm.setValue(3);
|
||||||
wrapper.update();
|
|
||||||
wrapper.vm.$nextTick(() => {
|
wrapper.vm.$nextTick(() => {
|
||||||
expect(wrapper.vm.currentValue).to.equal(3);
|
expect(wrapper.vm.currentValue).to.equal(3);
|
||||||
done();
|
done();
|
||||||
@ -192,77 +190,46 @@ describe('PickerColumn', () => {
|
|||||||
it('change picker-column values', (done) => {
|
it('change picker-column values', (done) => {
|
||||||
wrapper = mount(PickerColumn);
|
wrapper = mount(PickerColumn);
|
||||||
|
|
||||||
expect(wrapper.hasClass('van-picker-column')).to.be.true;
|
expect(wrapper.vm.options.length).to.equal(0);
|
||||||
expect(wrapper.vm.values.length).to.equal(0);
|
|
||||||
|
|
||||||
wrapper.vm.values = [1, 2];
|
wrapper.vm.options = [1, 2];
|
||||||
wrapper.update();
|
|
||||||
wrapper.vm.$nextTick(() => {
|
wrapper.vm.$nextTick(() => {
|
||||||
expect(wrapper.vm.values.length).to.equal(2);
|
expect(wrapper.vm.options.length).to.equal(2);
|
||||||
expect(wrapper.vm.currentValues.length).to.equal(2);
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('create a picker test translate', () => {
|
it('select disabled options', () => {
|
||||||
wrapper = mount(PickerColumn, {
|
wrapper = mount(PickerColumn, {
|
||||||
propsData: {
|
propsData: {
|
||||||
values: [1, 2, 3, 4, 5],
|
options: [
|
||||||
value: 1
|
{ text: '1', disabled: true },
|
||||||
|
{ text: '2' },
|
||||||
|
{ text: '3', disabled: true },
|
||||||
|
{ text: '4', disabled: true }
|
||||||
|
],
|
||||||
|
valueKey: 'text'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
expect(wrapper.vm.currentIndex).to.equal(1);
|
||||||
|
|
||||||
expect(wrapper.vm.values.length).to.equal(5);
|
wrapper.vm.setIndex(3);
|
||||||
expect(wrapper.vm.value2Translate(2)).to.equal((1 - Math.floor(5 / 2)) * (-itemHeight));
|
expect(wrapper.vm.currentIndex).to.equal(1);
|
||||||
expect(wrapper.vm.translate2Value(0)).to.equal(3);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('test draggable', done => {
|
it('drag options', () => {
|
||||||
wrapper = mount(PickerColumn, {
|
wrapper = mount(PickerColumn, {
|
||||||
propsData: {
|
propsData: {
|
||||||
values: [1, 2, 3, 4, 5]
|
options: pickerColumns[1].values
|
||||||
},
|
}
|
||||||
attachToDocument: true
|
|
||||||
});
|
});
|
||||||
|
expect(wrapper.vm.currentIndex).to.equal(0);
|
||||||
|
|
||||||
expect(wrapper.vm.values.length).to.equal(5);
|
const column = wrapper.find('.van-picker-column ul')[0];
|
||||||
|
dragHelper(column, 0);
|
||||||
|
expect(wrapper.vm.currentIndex).to.equal(0);
|
||||||
|
|
||||||
setTimeout(() => {
|
dragHelper(column, -100);
|
||||||
const nColumn = wrapper.find('.van-picker-column-wrapper')[0];
|
expect(wrapper.vm.currentIndex).to.equal(2);
|
||||||
|
|
||||||
const eventMouseObject = new window.Event('mousedown');
|
|
||||||
eventMouseObject.pageY = 0;
|
|
||||||
nColumn.element.dispatchEvent(eventMouseObject);
|
|
||||||
|
|
||||||
const eventTouchObject = new window.Event('touchstart');
|
|
||||||
eventTouchObject.changedTouches = [{ pageY: 0 }];
|
|
||||||
nColumn.element.dispatchEvent(eventTouchObject);
|
|
||||||
}, 500);
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
const nColumn = wrapper.find('.van-picker-column-wrapper')[0];
|
|
||||||
|
|
||||||
const eventMouseMoveObject = new window.Event('mousemove');
|
|
||||||
eventMouseMoveObject.pageY = 40;
|
|
||||||
document.dispatchEvent(eventMouseMoveObject);
|
|
||||||
|
|
||||||
const eventObject = new window.Event('touchmove');
|
|
||||||
eventObject.changedTouches = [{ pageY: 40 }];
|
|
||||||
nColumn.element.dispatchEvent(eventObject);
|
|
||||||
|
|
||||||
// 结束滚动
|
|
||||||
const eventMouseUpObject = new window.Event('mouseup');
|
|
||||||
document.dispatchEvent(eventMouseUpObject);
|
|
||||||
const eventEndObject = new window.Event('touchend');
|
|
||||||
eventEndObject.changedTouches = [{}];
|
|
||||||
nColumn.element.dispatchEvent(eventEndObject);
|
|
||||||
}, 1000);
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
const nItem = wrapper.find('.van-picker-column__item');
|
|
||||||
expect(nItem[1].hasClass('van-picker-column__item--selected')).to.be.true;
|
|
||||||
|
|
||||||
done();
|
|
||||||
}, 1200);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -82,8 +82,8 @@ describe('Sku', (done) => {
|
|||||||
|
|
||||||
const buyCallback = sinon.spy();
|
const buyCallback = sinon.spy();
|
||||||
const addCartCallback = sinon.spy();
|
const addCartCallback = sinon.spy();
|
||||||
const buyBtn = wrapper.find('.van-sku__buy-btn')[0];
|
const buyBtn = wrapper.find('.van-button--bottom-action')[1];
|
||||||
const addCartBtn = wrapper.find('.van-sku__add-cart-btn')[0];
|
const addCartBtn = wrapper.find('.van-button--bottom-action')[0];
|
||||||
wrapper.vm.$on('buy-clicked', buyCallback);
|
wrapper.vm.$on('buy-clicked', buyCallback);
|
||||||
wrapper.vm.$on('add-cart', addCartCallback);
|
wrapper.vm.$on('add-cart', addCartCallback);
|
||||||
|
|
||||||
@ -187,7 +187,7 @@ describe('Sku', (done) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const buyBtn = wrapper.find('.van-sku__buy-btn')[0];
|
const buyBtn = wrapper.find('.van-button--bottom-action')[0];
|
||||||
const skuMessages = wrapper.find('.van-sku-messages')[0];
|
const skuMessages = wrapper.find('.van-sku-messages')[0];
|
||||||
const inputs = skuMessages.find('input');
|
const inputs = skuMessages.find('input');
|
||||||
const textarea = skuMessages.find('textarea')[0];
|
const textarea = skuMessages.find('textarea')[0];
|
||||||
@ -272,7 +272,7 @@ describe('Sku', (done) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const buyBtn = wrapper.find('.van-sku__buy-btn')[0];
|
const buyBtn = wrapper.find('.van-button--bottom-action')[0];
|
||||||
|
|
||||||
wrapper.vm.$nextTick(() => {
|
wrapper.vm.$nextTick(() => {
|
||||||
buyBtn.trigger('click');
|
buyBtn.trigger('click');
|
||||||
|
@ -73,3 +73,12 @@ export function triggerTouch(wrapper, eventName, x, y) {
|
|||||||
|
|
||||||
el.dispatchEvent(event);
|
el.dispatchEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function dragHelper(el, position) {
|
||||||
|
triggerTouch(el, 'touchstart', 0, 0);
|
||||||
|
triggerTouch(el, 'touchmove', 0, position / 4);
|
||||||
|
triggerTouch(el, 'touchmove', 0, position / 3);
|
||||||
|
triggerTouch(el, 'touchmove', 0, position / 2);
|
||||||
|
triggerTouch(el, 'touchmove', 0, position);
|
||||||
|
triggerTouch(el, 'touchend', 0, position);
|
||||||
|
}
|
||||||
|
76
yarn.lock
76
yarn.lock
@ -56,11 +56,11 @@ ajv-keywords@^1.0.0:
|
|||||||
version "1.5.1"
|
version "1.5.1"
|
||||||
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c"
|
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c"
|
||||||
|
|
||||||
ajv-keywords@^2.0.0:
|
ajv-keywords@^2.0.0, ajv-keywords@^2.1.0:
|
||||||
version "2.1.1"
|
version "2.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-2.1.1.tgz#617997fc5f60576894c435f940d819e135b80762"
|
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-2.1.1.tgz#617997fc5f60576894c435f940d819e135b80762"
|
||||||
|
|
||||||
ajv@^4.11.2, ajv@^4.7.0, ajv@^4.9.1:
|
ajv@^4.7.0, ajv@^4.9.1:
|
||||||
version "4.11.8"
|
version "4.11.8"
|
||||||
resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536"
|
resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536"
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -300,7 +300,7 @@ async@1.x, async@^1.4.0, async@^1.5.2:
|
|||||||
version "1.5.2"
|
version "1.5.2"
|
||||||
resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
|
resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
|
||||||
|
|
||||||
async@2.6.0, async@^2.1.2:
|
async@2.6.0, async@^2.1.2, async@^2.4.1:
|
||||||
version "2.6.0"
|
version "2.6.0"
|
||||||
resolved "https://registry.yarnpkg.com/async/-/async-2.6.0.tgz#61a29abb6fcc026fea77e56d1c6ec53a795951f4"
|
resolved "https://registry.yarnpkg.com/async/-/async-2.6.0.tgz#61a29abb6fcc026fea77e56d1c6ec53a795951f4"
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -325,15 +325,15 @@ autoprefixer@^6.3.1:
|
|||||||
postcss "^5.2.16"
|
postcss "^5.2.16"
|
||||||
postcss-value-parser "^3.2.3"
|
postcss-value-parser "^3.2.3"
|
||||||
|
|
||||||
autoprefixer@^7.1.6:
|
autoprefixer@^7.2.1:
|
||||||
version "7.1.6"
|
version "7.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-7.1.6.tgz#fb933039f74af74a83e71225ce78d9fd58ba84d7"
|
resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-7.2.1.tgz#906b1447a0e6a9e13b371f7909bc4e36da5a5a79"
|
||||||
dependencies:
|
dependencies:
|
||||||
browserslist "^2.5.1"
|
browserslist "^2.9.1"
|
||||||
caniuse-lite "^1.0.30000748"
|
caniuse-lite "^1.0.30000777"
|
||||||
normalize-range "^0.1.2"
|
normalize-range "^0.1.2"
|
||||||
num2fraction "^1.2.2"
|
num2fraction "^1.2.2"
|
||||||
postcss "^6.0.13"
|
postcss "^6.0.14"
|
||||||
postcss-value-parser "^3.2.3"
|
postcss-value-parser "^3.2.3"
|
||||||
|
|
||||||
avoriaz@2.0.0:
|
avoriaz@2.0.0:
|
||||||
@ -1109,7 +1109,7 @@ browserslist@^1.3.6, browserslist@^1.5.2, browserslist@^1.7.6:
|
|||||||
caniuse-db "^1.0.30000639"
|
caniuse-db "^1.0.30000639"
|
||||||
electron-to-chromium "^1.2.7"
|
electron-to-chromium "^1.2.7"
|
||||||
|
|
||||||
browserslist@^2.1.2, browserslist@^2.5.1:
|
browserslist@^2.1.2, browserslist@^2.9.1:
|
||||||
version "2.9.1"
|
version "2.9.1"
|
||||||
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-2.9.1.tgz#b72d3982ab01b5cd24da62ff6d45573886aff275"
|
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-2.9.1.tgz#b72d3982ab01b5cd24da62ff6d45573886aff275"
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -1144,6 +1144,15 @@ bytes@3.0.0:
|
|||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048"
|
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048"
|
||||||
|
|
||||||
|
cache-loader@^1.2.0:
|
||||||
|
version "1.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/cache-loader/-/cache-loader-1.2.0.tgz#cdc313ae53b3c13ce8ee0c9296cf16c736b15252"
|
||||||
|
dependencies:
|
||||||
|
async "^2.4.1"
|
||||||
|
loader-utils "^1.1.0"
|
||||||
|
mkdirp "^0.5.1"
|
||||||
|
schema-utils "^0.4.2"
|
||||||
|
|
||||||
caller-path@^0.1.0:
|
caller-path@^0.1.0:
|
||||||
version "0.1.0"
|
version "0.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f"
|
resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f"
|
||||||
@ -1205,10 +1214,14 @@ caniuse-db@^1.0.30000529, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639:
|
|||||||
version "1.0.30000775"
|
version "1.0.30000775"
|
||||||
resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000775.tgz#04bccdd0214edf25b97f61a096609f7ad6904333"
|
resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000775.tgz#04bccdd0214edf25b97f61a096609f7ad6904333"
|
||||||
|
|
||||||
caniuse-lite@^1.0.30000748, caniuse-lite@^1.0.30000770:
|
caniuse-lite@^1.0.30000770:
|
||||||
version "1.0.30000775"
|
version "1.0.30000775"
|
||||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000775.tgz#74d27feddc47f3c84cfbcb130c3092a35ebc2de2"
|
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000775.tgz#74d27feddc47f3c84cfbcb130c3092a35ebc2de2"
|
||||||
|
|
||||||
|
caniuse-lite@^1.0.30000777:
|
||||||
|
version "1.0.30000778"
|
||||||
|
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000778.tgz#f1e7cb8b13b1f6744402291d75f0bcd4c3160369"
|
||||||
|
|
||||||
caseless@~0.12.0:
|
caseless@~0.12.0:
|
||||||
version "0.12.0"
|
version "0.12.0"
|
||||||
resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
|
resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
|
||||||
@ -2711,14 +2724,14 @@ extglob@^0.3.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
is-extglob "^1.0.0"
|
is-extglob "^1.0.0"
|
||||||
|
|
||||||
extract-text-webpack-plugin@2.0.0:
|
extract-text-webpack-plugin@3.0.2:
|
||||||
version "2.0.0"
|
version "3.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/extract-text-webpack-plugin/-/extract-text-webpack-plugin-2.0.0.tgz#8640f72609800a3528f13a2a9634d566a5c1ae60"
|
resolved "https://registry.yarnpkg.com/extract-text-webpack-plugin/-/extract-text-webpack-plugin-3.0.2.tgz#5f043eaa02f9750a9258b78c0a6e0dc1408fb2f7"
|
||||||
dependencies:
|
dependencies:
|
||||||
ajv "^4.11.2"
|
async "^2.4.1"
|
||||||
async "^2.1.2"
|
loader-utils "^1.1.0"
|
||||||
loader-utils "^1.0.2"
|
schema-utils "^0.3.0"
|
||||||
webpack-sources "^0.1.0"
|
webpack-sources "^1.0.1"
|
||||||
|
|
||||||
extract-zip@^1.6.5:
|
extract-zip@^1.6.5:
|
||||||
version "1.6.6"
|
version "1.6.6"
|
||||||
@ -6729,6 +6742,14 @@ schema-utils@^0.3.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
ajv "^5.0.0"
|
ajv "^5.0.0"
|
||||||
|
|
||||||
|
schema-utils@^0.4.2:
|
||||||
|
version "0.4.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-0.4.2.tgz#86d92aedf4dfc51c9b321ef16bd33a9417b122d0"
|
||||||
|
dependencies:
|
||||||
|
ajv "^5.0.0"
|
||||||
|
ajv-keywords "^2.1.0"
|
||||||
|
chalk "^2.3.0"
|
||||||
|
|
||||||
select-hose@^2.0.0:
|
select-hose@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca"
|
resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca"
|
||||||
@ -6952,10 +6973,6 @@ source-list-map@^2.0.0:
|
|||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.0.tgz#aaa47403f7b245a92fbc97ea08f250d6087ed085"
|
resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.0.tgz#aaa47403f7b245a92fbc97ea08f250d6087ed085"
|
||||||
|
|
||||||
source-list-map@~0.1.7:
|
|
||||||
version "0.1.8"
|
|
||||||
resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-0.1.8.tgz#c550b2ab5427f6b3f21f5afead88c4f5587b2106"
|
|
||||||
|
|
||||||
source-map-support@^0.4.15:
|
source-map-support@^0.4.15:
|
||||||
version "0.4.18"
|
version "0.4.18"
|
||||||
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f"
|
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f"
|
||||||
@ -6968,7 +6985,7 @@ source-map@0.4.x, source-map@^0.4.4:
|
|||||||
dependencies:
|
dependencies:
|
||||||
amdefine ">=0.0.4"
|
amdefine ">=0.0.4"
|
||||||
|
|
||||||
source-map@0.5.x, source-map@^0.5.0, source-map@^0.5.1, source-map@^0.5.3, source-map@^0.5.6, source-map@~0.5.1, source-map@~0.5.3, source-map@~0.5.6:
|
source-map@0.5.x, source-map@^0.5.0, source-map@^0.5.1, source-map@^0.5.3, source-map@^0.5.6, source-map@~0.5.1, source-map@~0.5.6:
|
||||||
version "0.5.7"
|
version "0.5.7"
|
||||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
|
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
|
||||||
|
|
||||||
@ -7848,13 +7865,6 @@ webpack-merge@^4.1.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
lodash "^4.17.4"
|
lodash "^4.17.4"
|
||||||
|
|
||||||
webpack-sources@^0.1.0:
|
|
||||||
version "0.1.5"
|
|
||||||
resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-0.1.5.tgz#aa1f3abf0f0d74db7111c40e500b84f966640750"
|
|
||||||
dependencies:
|
|
||||||
source-list-map "~0.1.7"
|
|
||||||
source-map "~0.5.3"
|
|
||||||
|
|
||||||
webpack-sources@^1.0.1:
|
webpack-sources@^1.0.1:
|
||||||
version "1.1.0"
|
version "1.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.1.0.tgz#a101ebae59d6507354d71d8013950a3a8b7a5a54"
|
resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.1.0.tgz#a101ebae59d6507354d71d8013950a3a8b7a5a54"
|
||||||
@ -7862,9 +7872,9 @@ webpack-sources@^1.0.1:
|
|||||||
source-list-map "^2.0.0"
|
source-list-map "^2.0.0"
|
||||||
source-map "~0.6.1"
|
source-map "~0.6.1"
|
||||||
|
|
||||||
webpack@^3.8.1:
|
webpack@^3.9.1:
|
||||||
version "3.8.1"
|
version "3.9.1"
|
||||||
resolved "https://registry.yarnpkg.com/webpack/-/webpack-3.8.1.tgz#b16968a81100abe61608b0153c9159ef8bb2bd83"
|
resolved "https://registry.yarnpkg.com/webpack/-/webpack-3.9.1.tgz#9a60aa544ed5d4d454c069e3f521aa007e02643c"
|
||||||
dependencies:
|
dependencies:
|
||||||
acorn "^5.0.0"
|
acorn "^5.0.0"
|
||||||
acorn-dynamic-import "^2.0.0"
|
acorn-dynamic-import "^2.0.0"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user