提交 42824b93 编写于 作者: J jerry

feat: picker

上级 bbce35bf
export default {
pages: [
'pages/picker/demo',
'pages/calendar/demo',
'pages/input/demo',
'pages/popup/demo',
......
<template>
<div class="demo">
<h2>基础用法</h2>
<nut-picker :list-data="listData1" @confirm="confirm">
<nut-cell title="请选择城市" :desc="desc"></nut-cell>
</nut-picker>
<h2>多列样式</h2>
<nut-cell title="请选择时间" :desc="desc2"></nut-cell>
<h2>多级联动</h2>
<nut-cell title="请选择地址" :desc="desc3"></nut-cell>
<!-- <nut-picker
v-model:visible="show2"
:list-data="listData2"
title="多列选择"
@confirm="confirm2"
@close="close"
></nut-picker>
<nut-picker
v-model:visible="show3"
:list-data="listData3"
title="地址选择"
@confirm="confirm3"
></nut-picker> -->
</div>
</template>
<script lang="ts">
import { toRefs, ref } from 'vue';
import { createComponent } from './../../../../../../packages/utils/create';
import Picker from './index.taro.vue';
import Cell from './../cell/index.taro.vue';
const { createDemo } = createComponent('picker');
export default createDemo({
components: {
'nut-picker': Picker,
'nut-cell': Cell
},
props: {},
setup() {
const listData1 = [
'南京市',
'无锡市',
'海北藏族自治区',
'北京市',
'连云港市',
'浙江市',
'江苏市'
];
const listData2 = [
{
values: ['周一', '周二', '周三', '周四', '周五'],
defaultIndex: 2
},
// 第二列
{
values: ['上午', '下午', '晚上'],
defaultIndex: 1
}
];
const listData3 = [
{
text: '浙江',
children: [
{
text: '杭州',
children: [{ text: '西湖区' }, { text: '余杭区' }]
},
{
text: '温州',
children: [{ text: '鹿城区' }, { text: '瓯海区' }]
}
]
},
{
text: '福建',
children: [
{
text: '福州',
children: [{ text: '鼓楼区' }, { text: '台江区' }]
},
{
text: '厦门',
children: [{ text: '思明区' }, { text: '海沧区' }]
}
]
}
];
const show = ref(false);
const show2 = ref(false);
const show3 = ref(false);
const showList = [show, show2, show3];
const desc = ref(listData1[0]);
const desc2 = ref(
`${listData2[0].values[listData2[0].defaultIndex]} ${
listData2[1].values[listData2[1].defaultIndex]
}`
);
const desc3 = ref(
`${listData3[0].text}
${listData3[0].children[0].text}
${listData3[0].children[0].children[0].text}`
);
const descList = [desc, desc2, desc3];
return {
listData1,
listData2,
listData3,
show,
show2,
show3,
desc,
desc2,
desc3,
open: (index: number) => {
showList[index - 1].value = true;
},
confirm: (res: any) => {
desc.value = res;
},
confirm2: (res: any) => {
desc2.value = res.join(' ');
},
confirm3: (res: any) => {
desc3.value = res.join(' ');
}
};
}
});
</script>
<template>
<view-block :class="classes">
<nut-popup
position="bottom"
:style="{ height: height + 56 + 'px' }"
v-model:visible="show"
@close="close"
>
<view-block class="nut-picker__bar">
<view-block class="nut-picker__left nut-picker__button" @click="close"
>取消</view-block
>
<view-block> {{ title }}</view-block>
<view-block class="nut-picker__button" @click="confirm()"
>确定</view-block
>
</view-block>
<view-block class="nut-picker__column">
<view-block
class="nut-picker__mask"
:style="{ backgroundSize: `100% ${top}px` }"
></view-block>
<view-block
class="nut-picker__hairline"
:style="{ top: ` ${top}px` }"
></view-block>
<view-block
class="nut-picker__columnitem"
v-for="(item, columnIndex) in columnList"
:key="columnIndex"
>
<nut-picker-column
:listData="item.values"
:readonly="readonly"
:defaultIndex="item.defaultIndex"
:visibleItemCount="visibleItemCount"
:itemHeight="itemHeight"
:dataType="dataType"
@change="
dataIndex => {
changeHandler(columnIndex, dataIndex);
}
"
></nut-picker-column>
</view-block>
</view-block>
</nut-popup>
</view-block>
<picker mode="selector" :range="listData" @change="onChange">
<slot></slot>
</picker>
</template>
<script lang="ts">
import { reactive, watch, computed, toRaw, toRefs } from 'vue';
import { createComponent } from '@/packages/utils/create';
import column from './Column.vue';
import popup from '@/packages/__VUE/popup/index.vue';
import { commonProps } from './commonProps';
import {
PickerObjOpt,
PickerOption,
PickerObjectColumn,
PickerObjectColumns
} from './types';
const { create, componentName } = createComponent('picker');
<script lang="ts">
const { create } = createComponent('picker');
import { commonProps } from '../../../../../../packages/__VUE/picker/commonProps';
import { createComponent } from './../../../../../../packages/utils/create';
export default create({
components: {
[column.name]: column,
[popup.name]: popup
},
props: {
visible: {
type: Boolean,
default: false
},
title: {
type: String,
default: ''
},
...commonProps
},
emits: ['close', 'change', 'confirm', 'update:visible'],
emits: ['confirm'],
setup(props, { emit }) {
const childrenKey = 'children';
const valuesKey = 'values';
const state = reactive({
show: false,
formattedColumns: props.listData as PickerObjectColumn[],
defaultIndex: props.defaultIndex as number
});
//临时变量,当点击确定时候赋值
let _defaultIndex = props.defaultIndex;
let defaultIndexList: number[] = [];
const classes = computed(() => {
const prefixCls = componentName;
return {
[prefixCls]: true
};
});
const top = computed(() => {
return (Number(+props.visibleItemCount - 1) / 2) * +props.itemHeight;
});
const height = computed(() => {
return Number(props.visibleItemCount) * +props.itemHeight;
});
const dataType = computed(() => {
const firstColumn = state.formattedColumns[0] as PickerObjectColumn;
if (typeof firstColumn === 'object') {
if (firstColumn[childrenKey]) {
return 'cascade';
} else if (firstColumn?.[valuesKey]) {
addDefaultIndexList(props.listData as PickerObjectColumn[]);
return 'multipleColumns';
}
}
return 'text';
});
const columnList = computed(() => {
if (dataType.value === 'text') {
return [
{ values: state.formattedColumns, defaultIndex: state.defaultIndex }
];
} else if (dataType.value === 'multipleColumns') {
return state.formattedColumns;
} else if (dataType.value === 'cascade') {
return formatCascade(
state.formattedColumns as PickerObjectColumn[],
state.defaultIndex
);
}
return state.formattedColumns;
});
const addDefaultIndexList = (listData: PickerObjectColumn[]) => {
defaultIndexList = [];
listData.forEach(res => {
defaultIndexList.push((res.defaultIndex as number) || 0);
});
const onChange = (e: any) => {
emit('confirm', props.listData[e.detail.value]);
};
const formatCascade = (
listData: PickerObjectColumn[],
defaultIndex: number
) => {
const formatted: PickerObjectColumn[] = [];
let children = listData as PickerObjectColumns;
children.defaultIndex = defaultIndex;
while (children) {
formatted.push({
values: children,
defaultIndex: children.defaultIndex || 0
});
children = children?.[children.defaultIndex || 0].children;
}
addDefaultIndexList(formatted);
return formatted;
};
const getCascadeData = (
listData: PickerObjectColumn[],
defaultIndex: number
) => {
let arr = listData as PickerObjectColumns;
arr.defaultIndex = defaultIndex;
const dataList: string[] = [];
while (arr) {
const item = arr[arr.defaultIndex ?? 0];
dataList.push(item.text as string);
arr = item.children;
}
return dataList;
};
const close = () => {
emit('close');
emit('update:visible', false);
};
const changeHandler = (columnIndex: number, dataIndex: number) => {
if (dataType.value === 'cascade') {
let cursor = state.formattedColumns as PickerObjectColumns;
if (columnIndex === 0) {
state.defaultIndex = dataIndex;
}
let i = 0;
while (cursor) {
if (i === columnIndex) {
cursor.defaultIndex = dataIndex;
} else if (i > columnIndex) {
cursor.defaultIndex = 0;
}
cursor = cursor[cursor.defaultIndex || 0].children;
i++;
}
} else if (dataType.value === 'text') {
_defaultIndex = dataIndex;
} else if (dataType.value === 'multipleColumns') {
defaultIndexList[columnIndex] = dataIndex;
const val = defaultIndexList.map(
(res, i) =>
toRaw(state.formattedColumns as PickerObjectColumns)[i].values[res]
);
emit('change', val);
}
};
const confirm = () => {
if (dataType.value === 'text') {
state.defaultIndex = _defaultIndex as number;
emit('confirm', state.formattedColumns[_defaultIndex as number]);
} else if (dataType.value === 'multipleColumns') {
for (let i = 0; i < defaultIndexList.length; i++) {
state.formattedColumns[i].defaultIndex = defaultIndexList[i];
}
const checkedArr = toRaw(state.formattedColumns).map(
(res: PickerObjectColumn) =>
res.values && res.values[res.defaultIndex as number]
);
emit('confirm', checkedArr);
} else if (dataType.value === 'cascade') {
emit(
'confirm',
getCascadeData(toRaw(state.formattedColumns), state.defaultIndex)
);
}
emit('update:visible', false);
};
watch(
() => props.visible,
val => {
state.show = val;
}
);
watch(
() => props.listData,
val => {
state.formattedColumns = val as PickerObjectColumns;
}
);
return {
classes,
...toRefs(state),
column,
dataType,
columnList,
top,
height,
close,
changeHandler,
confirm
confirm,
onChange
};
}
});
</script>
<style lang="scss">
@import 'index.scss';
</style>
<style lang="scss" scoped></style>
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册