mirror of
https://gitee.com/vant-contrib/vant-weapp.git
synced 2025-04-05 19:41:45 +08:00
[new feature] Picker: add new component Picker
This commit is contained in:
parent
c1faa8b130
commit
3cb142b8f5
@ -37,7 +37,8 @@
|
||||
"pages/swipe-cell/index",
|
||||
"pages/datetime-picker/index",
|
||||
"pages/rate/index",
|
||||
"pages/collapse/index"
|
||||
"pages/collapse/index",
|
||||
"pages/picker/index"
|
||||
],
|
||||
"window": {
|
||||
"navigationBarBackgroundColor": "#f8f8f8",
|
||||
@ -94,6 +95,7 @@
|
||||
"van-datetime-picker": "../../dist/datetime-picker/index",
|
||||
"van-rate": "../../dist/rate/index",
|
||||
"van-collapse": "../../dist/collapse/index",
|
||||
"van-collapse-item": "../../dist/collapse-item/index"
|
||||
"van-collapse-item": "../../dist/collapse-item/index",
|
||||
"van-picker": "../../dist/picker/index"
|
||||
}
|
||||
}
|
||||
|
@ -43,6 +43,10 @@ export default [
|
||||
path: '/field',
|
||||
title: 'Field 输入框'
|
||||
},
|
||||
{
|
||||
path: '/picker',
|
||||
title: 'Picker 选择器'
|
||||
},
|
||||
{
|
||||
path: '/radio',
|
||||
title: 'Radio 单选框'
|
||||
|
48
example/pages/picker/index.js
Normal file
48
example/pages/picker/index.js
Normal file
@ -0,0 +1,48 @@
|
||||
import Page from '../../common/page';
|
||||
import Toast from '../../dist/toast/toast';
|
||||
|
||||
Page({
|
||||
data: {
|
||||
column1: ['杭州', '宁波', '温州', '嘉兴', '湖州'],
|
||||
column2: [
|
||||
{ text: '杭州', disabled: true },
|
||||
{ text: '宁波' },
|
||||
{ text: '温州' }
|
||||
],
|
||||
column3: {
|
||||
浙江: ['杭州', { text: '宁波' }, { text: '温州', disabled: true }, '嘉兴', '湖州'],
|
||||
福建: ['福州', '厦门', '莆田', '三明', '泉州']
|
||||
},
|
||||
column4: [
|
||||
{
|
||||
values: ['浙江', '福建'],
|
||||
className: 'column1'
|
||||
},
|
||||
{
|
||||
values: ['杭州', '宁波', '温州', '嘉兴', '湖州'],
|
||||
className: 'column2',
|
||||
defaultIndex: 2
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
onChange1(event) {
|
||||
const { value, index } = event.detail;
|
||||
Toast(`Value: ${value}, Index:${index}`);
|
||||
},
|
||||
|
||||
onConfirm(event) {
|
||||
const { value, index } = event.detail;
|
||||
Toast(`Value: ${value}, Index:${index}`);
|
||||
},
|
||||
|
||||
onCancel() {
|
||||
Toast('取消');
|
||||
},
|
||||
|
||||
onChange2(event) {
|
||||
const { picker, value } = event.detail;
|
||||
picker.setColumnValues(1, this.data.column3[value[0]]);
|
||||
getApp().picker = picker;
|
||||
}
|
||||
});
|
3
example/pages/picker/index.json
Normal file
3
example/pages/picker/index.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"navigationBarTitleText": "Picker 选择器"
|
||||
}
|
39
example/pages/picker/index.wxml
Normal file
39
example/pages/picker/index.wxml
Normal file
@ -0,0 +1,39 @@
|
||||
<demo-block title="基础用法">
|
||||
<van-picker
|
||||
columns="{{ column1 }}"
|
||||
bind:change="onChange1"
|
||||
/>
|
||||
</demo-block>
|
||||
|
||||
<demo-block title="禁用选项">
|
||||
<van-picker
|
||||
columns="{{ column2 }}"
|
||||
/>
|
||||
</demo-block>
|
||||
|
||||
<demo-block title="展示顶部栏">
|
||||
<van-picker
|
||||
show-toolbar
|
||||
title="标题"
|
||||
columns="{{ column1 }}"
|
||||
bind:change="onChange1"
|
||||
bind:confirm="onConfirm"
|
||||
bind:cancel="onCancel"
|
||||
/>
|
||||
</demo-block>
|
||||
|
||||
<demo-block title="多列联动">
|
||||
<van-picker
|
||||
columns="{{ column4 }}"
|
||||
bind:change="onChange2"
|
||||
/>
|
||||
</demo-block>
|
||||
|
||||
<demo-block title="加载状态">
|
||||
<van-picker
|
||||
loading
|
||||
columns="{{ column4 }}"
|
||||
/>
|
||||
</demo-block>
|
||||
|
||||
<van-toast id="van-toast" />
|
0
example/pages/picker/index.wxss
Normal file
0
example/pages/picker/index.wxss
Normal file
@ -11,8 +11,13 @@ function isNumber(value) {
|
||||
return /^\d+$/.test(value);
|
||||
}
|
||||
|
||||
function range(num: number, min: number, max: number) {
|
||||
return Math.min(Math.max(num, min), max);
|
||||
}
|
||||
|
||||
export {
|
||||
isObj,
|
||||
isDef,
|
||||
isNumber
|
||||
isNumber,
|
||||
range
|
||||
};
|
||||
|
3
packages/picker-column/index.json
Normal file
3
packages/picker-column/index.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"component": true
|
||||
}
|
21
packages/picker-column/index.less
Normal file
21
packages/picker-column/index.less
Normal file
@ -0,0 +1,21 @@
|
||||
@import '../common/style/var';
|
||||
|
||||
.van-picker-column {
|
||||
overflow: hidden;
|
||||
font-size: 16px;
|
||||
text-align: center;
|
||||
|
||||
&__item {
|
||||
padding: 0 5px;
|
||||
color: @gray-dark;
|
||||
|
||||
&--selected {
|
||||
font-weight: 500;
|
||||
color: @text-color;
|
||||
}
|
||||
|
||||
&--disabled {
|
||||
opacity: 0.3;
|
||||
}
|
||||
}
|
||||
}
|
160
packages/picker-column/index.ts
Normal file
160
packages/picker-column/index.ts
Normal file
@ -0,0 +1,160 @@
|
||||
import { VantComponent } from '../common/component';
|
||||
import { isObj, range } from '../common/utils';
|
||||
|
||||
const DEFAULT_DURATION = 200;
|
||||
|
||||
VantComponent({
|
||||
classes: ['active-class'],
|
||||
|
||||
props: {
|
||||
valueKey: String,
|
||||
className: String,
|
||||
itemHeight: Number,
|
||||
visibleItemCount: Number,
|
||||
initialOptions: {
|
||||
type: Array,
|
||||
value: []
|
||||
},
|
||||
defaultIndex: {
|
||||
type: Number,
|
||||
value: 0
|
||||
}
|
||||
},
|
||||
|
||||
data: {
|
||||
startY: 0,
|
||||
offset: 0,
|
||||
duration: 0,
|
||||
startOffset: 0,
|
||||
options: [],
|
||||
currentIndex: 0
|
||||
},
|
||||
|
||||
created() {
|
||||
const { defaultIndex, initialOptions } = this.data;
|
||||
this.set({
|
||||
currentIndex: defaultIndex,
|
||||
options: initialOptions
|
||||
});
|
||||
},
|
||||
|
||||
computed: {
|
||||
count() {
|
||||
return this.data.options.length;
|
||||
},
|
||||
|
||||
baseOffset() {
|
||||
const { data } = this;
|
||||
return (data.itemHeight * (data.visibleItemCount - 1)) / 2;
|
||||
},
|
||||
|
||||
wrapperStyle() {
|
||||
const { data } = this;
|
||||
return [
|
||||
`transition: ${data.duration}ms`,
|
||||
`transform: translate3d(0, ${data.offset + data.baseOffset}px, 0)`,
|
||||
`line-height: ${data.itemHeight}px`
|
||||
].join('; ');
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
defaultIndex(value: number) {
|
||||
this.setIndex(value);
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
onTouchStart(event: Weapp.TouchEvent) {
|
||||
this.set({
|
||||
startY: event.touches[0].clientY,
|
||||
startOffset: this.data.offset,
|
||||
duration: 0
|
||||
});
|
||||
},
|
||||
|
||||
onTouchMove(event: Weapp.TouchEvent) {
|
||||
const { data } = this;
|
||||
const deltaY = event.touches[0].clientY - data.startY;
|
||||
this.set({
|
||||
offset: range(
|
||||
data.startOffset + deltaY,
|
||||
-(data.count * data.itemHeight),
|
||||
data.itemHeight
|
||||
)
|
||||
});
|
||||
},
|
||||
|
||||
onTouchEnd() {
|
||||
const { data } = this;
|
||||
if (data.offset !== data.startOffset) {
|
||||
this.set({
|
||||
duration: DEFAULT_DURATION
|
||||
});
|
||||
const index = range(
|
||||
Math.round(-data.offset / data.itemHeight),
|
||||
0,
|
||||
data.count - 1
|
||||
);
|
||||
this.setIndex(index, true);
|
||||
}
|
||||
},
|
||||
|
||||
onClickItem(event: Weapp.Event) {
|
||||
const { index } = event.currentTarget.dataset;
|
||||
this.setIndex(index, true);
|
||||
},
|
||||
|
||||
adjustIndex(index: number) {
|
||||
const { data } = this;
|
||||
index = range(index, 0, data.count);
|
||||
for (let i = index; i < data.count; i++) {
|
||||
if (!this.isDisabled(data.options[i])) return i;
|
||||
}
|
||||
for (let i = index - 1; i >= 0; i--) {
|
||||
if (!this.isDisabled(data.options[i])) return i;
|
||||
}
|
||||
},
|
||||
|
||||
isDisabled(option: any) {
|
||||
return isObj(option) && option.disabled;
|
||||
},
|
||||
|
||||
getOptionText(option: any) {
|
||||
const { data } = this;
|
||||
return isObj(option) && data.valueKey in option
|
||||
? option[data.valueKey]
|
||||
: option;
|
||||
},
|
||||
|
||||
setIndex(index: number, userAction: boolean) {
|
||||
const { data } = this;
|
||||
index = this.adjustIndex(index) || 0;
|
||||
|
||||
this.set({
|
||||
offset: -index * data.itemHeight
|
||||
});
|
||||
|
||||
if (index !== data.currentIndex) {
|
||||
this.set({
|
||||
currentIndex: index
|
||||
});
|
||||
userAction && this.$emit('change', index);
|
||||
}
|
||||
},
|
||||
|
||||
setValue(value: string) {
|
||||
const { options } = this.data;
|
||||
for (let i = 0; i < options.length; i++) {
|
||||
if (this.getOptionText(options[i]) === value) {
|
||||
return this.setIndex(i);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
getValue() {
|
||||
const { data } = this;
|
||||
return data.options[data.currentIndex];
|
||||
}
|
||||
}
|
||||
});
|
31
packages/picker-column/index.wxml
Normal file
31
packages/picker-column/index.wxml
Normal file
@ -0,0 +1,31 @@
|
||||
<view
|
||||
class="van-picker-column custom-class"
|
||||
style="height: {{ itemHeight * visibleItemCount }}px"
|
||||
bind:touchstart="onTouchStart"
|
||||
catch:touchmove="onTouchMove"
|
||||
bind:touchend="onTouchEnd"
|
||||
bind:touchcancel="onTouchEnd"
|
||||
>
|
||||
<view style="{{ wrapperStyle }}">
|
||||
<view
|
||||
wx:for="{{ options }}"
|
||||
wx:for-item="option"
|
||||
wx:key="index"
|
||||
data-index="{{ index }}"
|
||||
style="height: {{ itemHeight }}px"
|
||||
class="van-ellipsis van-picker-column__item {{ option && option.disabled ? 'van-picker-column__item--disabled' : '' }} {{ index === currentIndex ? 'van-picker-column__item--selected active-class' : '' }}"
|
||||
bindtap="onClickItem"
|
||||
>{{ getOptionText(option, valueKey) }}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<wxs module="getOptionText">
|
||||
function isObj(x) {
|
||||
var type = typeof x;
|
||||
return x !== null && (type === 'object' || type === 'function');
|
||||
}
|
||||
|
||||
module.exports = function (option, valueKey) {
|
||||
return isObj(option) && option[valueKey] ? option[valueKey] : option;
|
||||
}
|
||||
</wxs>
|
185
packages/picker/README.md
Normal file
185
packages/picker/README.md
Normal file
@ -0,0 +1,185 @@
|
||||
## Picker 选择器
|
||||
选择器组件通常与 [弹出层](#/popup) 组件配合使用
|
||||
|
||||
### 使用指南
|
||||
在 app.json 或 index.json 中引入组件
|
||||
```json
|
||||
"usingComponents": {
|
||||
"van-picker": "path/to/vant-weapp/dist/picker/index"
|
||||
}
|
||||
```
|
||||
|
||||
### 代码演示
|
||||
|
||||
|
||||
#### 基础用法
|
||||
|
||||
```html
|
||||
<van-picker columns="{{ columns }}" bind:change="onChange" />
|
||||
```
|
||||
|
||||
```javascript
|
||||
import Toast from 'path/to/vant-weapp/dist/toast/toast';
|
||||
|
||||
Page({
|
||||
data: {
|
||||
columns: ['杭州', '宁波', '温州', '嘉兴', '湖州']
|
||||
},
|
||||
|
||||
onChange(event) {
|
||||
const { picker, value, index } = event.detail;
|
||||
Toast(`当前值:${value}, 当前索引:${index}`);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
#### 禁用选项
|
||||
选项可以为对象结构,通过设置 disabled 来禁用该选项
|
||||
|
||||
```html
|
||||
<van-picker columns="{{ columns }}" />
|
||||
```
|
||||
|
||||
```javascript
|
||||
Page({
|
||||
data: {
|
||||
columns: [
|
||||
{ text: '杭州', disabled: true },
|
||||
{ text: '宁波' },
|
||||
{ text: '温州' }
|
||||
]
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
#### 展示顶部栏
|
||||
|
||||
```html
|
||||
<van-picker
|
||||
show-toolbar
|
||||
title="标题"
|
||||
columns="{{ columns }}"
|
||||
bind:cancel="onCancel"
|
||||
bind:confirm="onConfirm"
|
||||
/>
|
||||
```
|
||||
|
||||
```javascript
|
||||
import Toast from 'path/to/vant-weapp/dist/toast/toast';
|
||||
|
||||
Page({
|
||||
data: {
|
||||
columns: ['杭州', '宁波', '温州', '嘉兴', '湖州']
|
||||
},
|
||||
|
||||
onConfirm(event) {
|
||||
const { picker, value, index } = event.detail;
|
||||
Toast(`当前值:${value}, 当前索引:${index}`);
|
||||
},
|
||||
|
||||
onCancel() {
|
||||
Toast('取消');
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
#### 多列联动
|
||||
|
||||
```html
|
||||
<van-picker columns="{{ columns }}" bind:change="onChange" />
|
||||
```
|
||||
|
||||
```javascript
|
||||
const citys = {
|
||||
'浙江': ['杭州', '宁波', '温州', '嘉兴', '湖州'],
|
||||
'福建': ['福州', '厦门', '莆田', '三明', '泉州']
|
||||
};
|
||||
|
||||
Page({
|
||||
data: {
|
||||
columns: [
|
||||
{
|
||||
values: Object.keys(citys),
|
||||
className: 'column1'
|
||||
},
|
||||
{
|
||||
values: citys['浙江'],
|
||||
className: 'column2',
|
||||
defaultIndex: 2
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
onChange(event) {
|
||||
const { picker, value, index } = event.detail;
|
||||
picker.setColumnValues(1, citys[values[0]]);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
#### 加载状态
|
||||
当 Picker 数据是通过异步获取时,可以通过 `loading` 属性显示加载提示
|
||||
|
||||
```html
|
||||
<van-picker columns="{{ columns }}" loading />
|
||||
```
|
||||
|
||||
### API
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||
|------|------|------|------|------|
|
||||
| columns | 对象数组,配置每一列显示的数据 | `Array` | `[]` | - |
|
||||
| show-toolbar | 是否显示顶部栏 | `Boolean` | `false` | - |
|
||||
| title | 顶部栏标题 | `String` | `''` | - |
|
||||
| loading | 是否显示加载状态 | `Boolean` | `false` | - |
|
||||
| value-key | 选项对象中,文字对应的 key | `String` | `text` | - |
|
||||
| item-height | 选项高度 | `Number` | `44` | - |
|
||||
| confirm-button-text | 确认按钮文字 | `String` | `确认` | - |
|
||||
| cancel-button-text | 取消按钮文字 | `String` | `取消` | - |
|
||||
| visible-item-count | 可见的选项个数 | `Number` | `5` | - |
|
||||
|
||||
### Event
|
||||
|
||||
Picker 组件的事件会根据 columns 是单列或多列返回不同的参数
|
||||
|
||||
| 事件名 | 说明 | 参数 |
|
||||
|------|------|------|
|
||||
| confirm | 点击完成按钮时触发 | 单列:选中值,选中值对应的索引<br>多列:所有列选中值,所有列选中值对应的索引 |
|
||||
| cancel | 点击取消按钮时触发 | 单列:选中值,选中值对应的索引<br>多列:所有列选中值,所有列选中值对应的索引 |
|
||||
| change | 选项改变时触发 | 单列:Picker 实例,选中值,选中值对应的索引<br>多列:Picker 实例,所有列选中值,当前列对应的索引 |
|
||||
|
||||
|
||||
### Columns 数据结构
|
||||
|
||||
当传入多列数据时,`columns`为一个对象数组,数组中的每一个对象配置每一列,每一列有以下`key`
|
||||
|
||||
| key | 说明 |
|
||||
|------|------|
|
||||
| values | 列中对应的备选值 |
|
||||
| defaultIndex | 初始选中项的索引,默认为 0 |
|
||||
|
||||
### 外部样式类
|
||||
|
||||
| 类名 | 说明 |
|
||||
|-----------|-----------|
|
||||
| custom-class | 根节点样式类 |
|
||||
| active-class | 选中项样式类 |
|
||||
| toolbar-class | 顶部栏样式类 |
|
||||
| column-class | 列样式类 |
|
||||
|
||||
### 方法
|
||||
|
||||
通过 selectComponent 可以获取到 picker 实例并调用实例方法
|
||||
|
||||
| 方法名 | 参数 | 返回值 | 介绍 |
|
||||
|------|------|------|------|
|
||||
| getValues | - | values | 获取所有列选中的值 |
|
||||
| setValues | values | - | 设置所有列选中的值 |
|
||||
| getIndexes | - | indexes | 获取所有列选中值对应的索引 |
|
||||
| setIndexes | indexes | - | 设置所有列选中值对应的索引 |
|
||||
| getColumnValue | columnIndex | value | 获取对应列选中的值 |
|
||||
| setColumnValue | columnIndex, value | - | 设置对应列选中的值 |
|
||||
| getColumnIndex | columnIndex | optionIndex | 获取对应列选中项的索引 |
|
||||
| setColumnIndex | columnIndex, optionIndex | - | 设置对应列选中项的索引 |
|
||||
| getColumnValues | columnIndex | values | 获取对应列中所有选项 |
|
||||
| setColumnValues | columnIndex, values | - | 设置对应列中所有选项 |
|
7
packages/picker/index.json
Normal file
7
packages/picker/index.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"picker-column": "../picker-column/index",
|
||||
"loading": "../loading/index"
|
||||
}
|
||||
}
|
67
packages/picker/index.less
Normal file
67
packages/picker/index.less
Normal file
@ -0,0 +1,67 @@
|
||||
@import '../common/style/var';
|
||||
|
||||
.van-picker {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
-webkit-text-size-adjust: 100%; /* avoid iOS text size adjust */
|
||||
background-color: @white;
|
||||
user-select: none;
|
||||
|
||||
&__toolbar {
|
||||
display: flex;
|
||||
height: 44px;
|
||||
line-height: 44px;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
&__cancel,
|
||||
&__confirm {
|
||||
padding: 0 15px;
|
||||
font-size: 14px;
|
||||
color: @blue;
|
||||
|
||||
&:active {
|
||||
background-color: @active-color;
|
||||
}
|
||||
}
|
||||
|
||||
&__title {
|
||||
max-width: 50%;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
&__columns {
|
||||
position: relative;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
&__column {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
&__loading {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 4;
|
||||
display: flex;
|
||||
background-color: rgba(255, 255, 255, 0.9);
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
&__loading .van-loading,
|
||||
&__frame {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 0;
|
||||
z-index: 1;
|
||||
width: 100%;
|
||||
pointer-events: none;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
}
|
154
packages/picker/index.ts
Normal file
154
packages/picker/index.ts
Normal file
@ -0,0 +1,154 @@
|
||||
import { VantComponent } from '../common/component';
|
||||
|
||||
VantComponent({
|
||||
classes: ['active-class', 'toolbar-class', 'column-class'],
|
||||
|
||||
props: {
|
||||
title: String,
|
||||
loading: Boolean,
|
||||
showToolbar: Boolean,
|
||||
confirmButtonText: String,
|
||||
cancelButtonText: String,
|
||||
visibleItemCount: {
|
||||
type: Number,
|
||||
value: 5
|
||||
},
|
||||
valueKey: {
|
||||
type: String,
|
||||
value: 'text'
|
||||
},
|
||||
itemHeight: {
|
||||
type: Number,
|
||||
value: 44
|
||||
},
|
||||
columns: {
|
||||
type: Array,
|
||||
value: [],
|
||||
observer(columns = []) {
|
||||
this.set({
|
||||
simple: columns.length && !columns[0].values
|
||||
}, () => {
|
||||
const children = this.children = this.selectAllComponents('.van-picker__column');
|
||||
|
||||
if (Array.isArray(children) && children.length) {
|
||||
this.setColumns();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
noop() {},
|
||||
|
||||
setColumns() {
|
||||
const { data } = this;
|
||||
const columns = data.simple ? [{ values: data.columns }] : data.columns;
|
||||
columns.forEach((columns, index: number) => {
|
||||
this.setColumnValues(index, columns.values);
|
||||
});
|
||||
},
|
||||
|
||||
emit(event: Weapp.Event) {
|
||||
const { type } = event.currentTarget.dataset;
|
||||
if (this.data.simple) {
|
||||
this.$emit(type, {
|
||||
value: this.getColumnValue(0),
|
||||
index: this.getColumnIndex(0)
|
||||
});
|
||||
} else {
|
||||
this.$emit(type, {
|
||||
value: this.getValues(),
|
||||
index: this.getIndexes()
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
onChange(event: Weapp.Event) {
|
||||
if (this.data.simple) {
|
||||
this.$emit('change', {
|
||||
picker: this,
|
||||
value: this.getColumnValue(0),
|
||||
index: this.getColumnIndex(0)
|
||||
});
|
||||
} else {
|
||||
this.$emit('change', {
|
||||
picker: this,
|
||||
value: this.getValues(),
|
||||
index: event.currentTarget.dataset.index
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// get column instance by index
|
||||
getColumn(index: number) {
|
||||
return this.children[index];
|
||||
},
|
||||
|
||||
// get column value by index
|
||||
getColumnValue(index: number) {
|
||||
const column = this.getColumn(index);
|
||||
return column && column.getValue();
|
||||
},
|
||||
|
||||
// set column value by index
|
||||
setColumnValue(index: number, value: any) {
|
||||
const column = this.getColumn(index);
|
||||
column && column.setValue(value);
|
||||
},
|
||||
|
||||
// get column option index by column index
|
||||
getColumnIndex(columnIndex: number) {
|
||||
return (this.getColumn(columnIndex) || {}).data.currentIndex;
|
||||
},
|
||||
|
||||
// set column option index by column index
|
||||
setColumnIndex(columnIndex: number, optionIndex: number) {
|
||||
const column = this.getColumn(columnIndex);
|
||||
column && column.setIndex(optionIndex);
|
||||
},
|
||||
|
||||
// get options of column by index
|
||||
getColumnValues(index: number) {
|
||||
return (this.children[index] || {}).data.options;
|
||||
},
|
||||
|
||||
// set options of column by index
|
||||
setColumnValues(index: number, options: any[]) {
|
||||
const column = this.children[index];
|
||||
|
||||
if (
|
||||
column &&
|
||||
JSON.stringify(column.data.options) !== JSON.stringify(options)
|
||||
) {
|
||||
column.set({ options }, () => {
|
||||
column.setIndex(0);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// get values of all columns
|
||||
getValues() {
|
||||
return this.children.map((child: Weapp.Component) => child.getValue());
|
||||
},
|
||||
|
||||
// set values of all columns
|
||||
setValues(values: []) {
|
||||
values.forEach((value, index) => {
|
||||
this.setColumnValue(index, value);
|
||||
});
|
||||
},
|
||||
|
||||
// get indexes of all columns
|
||||
getIndexes() {
|
||||
return this.children.map((child: Weapp.Component) => child.data.currentIndex);
|
||||
},
|
||||
|
||||
// set indexes of all columns
|
||||
setIndexes(indexes: number[]) {
|
||||
indexes.forEach((optionIndex, columnIndex) => {
|
||||
this.setColumnIndex(columnIndex, optionIndex);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
41
packages/picker/index.wxml
Normal file
41
packages/picker/index.wxml
Normal file
@ -0,0 +1,41 @@
|
||||
<view class="van-picker custom-class">
|
||||
<view
|
||||
wx:if="{{ showToolbar }}"
|
||||
class="van-picker__toolbar van-hairline--top-bottom toolbar-class"
|
||||
>
|
||||
<view class="van-picker__cancel" data-type="cancel" bindtap="emit">
|
||||
{{ cancelButtonText || '取消' }}
|
||||
</view>
|
||||
<view wx:if="{{ title }}" class="van-picker__title van-ellipsis">{{ title }}</view>
|
||||
<view class="van-picker__confirm" data-type="confirm" bindtap="emit">
|
||||
{{ confirmButtonText || '确认' }}
|
||||
</view>
|
||||
</view>
|
||||
<view wx:if="{{ loading }}" class="van-picker__loading">
|
||||
<loading color="#1989fa"/>
|
||||
</view>
|
||||
<view
|
||||
class="van-picker__columns"
|
||||
style="height: {{ itemHeight * visibleItemCount }}px"
|
||||
catch:touchmove="noop"
|
||||
>
|
||||
<picker-column
|
||||
class="van-picker__column"
|
||||
wx:for="{{ simple ? [columns] : columns }}"
|
||||
wx:key="index"
|
||||
data-index="{{ index }}"
|
||||
custom-class="column-class"
|
||||
value-key="{{ valueKey }}"
|
||||
initial-options="{{ simple ? item : item.values }}"
|
||||
default-index="{{ item.defaultIndex }}"
|
||||
item-height="{{ itemHeight }}"
|
||||
visible-item-count="{{ visibleItemCount }}"
|
||||
active-class="active-class"
|
||||
bind:change="onChange"
|
||||
/>
|
||||
<view
|
||||
class="van-picker__frame van-hairline--top-bottom"
|
||||
style="height: {{ itemHeight }}px"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
Loading…
x
Reference in New Issue
Block a user