types(Area): use tsx (#8140)

This commit is contained in:
neverland 2021-02-12 13:18:13 +08:00 committed by GitHub
parent 54be2b3c0a
commit a00f599dc2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 83 additions and 52 deletions

View File

@ -93,8 +93,8 @@ To have a selected valuesimply pass the `code` of target area to `value` prop
Use [ref](https://v3.vuejs.org/guide/component-template-refs.html) to get Area instance and call instance methods. Use [ref](https://v3.vuejs.org/guide/component-template-refs.html) to get Area instance and call instance methods.
| Name | Description | Attribute | Return value | | Name | Description | Attribute | Return value |
| ----- | ------------------------- | ------------- | ------------ | | ----- | ------------------------- | --------------- | ------------ |
| reset | Reset all options by code | code?: string | - | | reset | Reset all options by code | _code?: string_ | - |
### areaList Data Structure ### areaList Data Structure

View File

@ -94,7 +94,7 @@ app.use(Area);
| 方法名 | 说明 | 参数 | 返回值 | | 方法名 | 说明 | 参数 | 返回值 |
| --- | --- | --- | --- | | --- | --- | --- | --- |
| reset | 根据 code 重置所有选项,若不传 code则重置到第一项 | code?: string | - | | reset | 根据 code 重置所有选项,若不传 code则重置到第一项 | _code?: string_ | - |
### 省市区列表数据格式 ### 省市区列表数据格式

View File

@ -1,27 +1,48 @@
import { ref, watch, computed, reactive, nextTick, onMounted } from 'vue'; /* eslint-disable camelcase */
import {
ref,
watch,
computed,
reactive,
nextTick,
PropType,
onMounted,
ComponentPublicInstance,
} from 'vue';
// Utils
import { deepClone } from '../utils/deep-clone';
import { createNamespace, pick } from '../utils'; import { createNamespace, pick } from '../utils';
// Composition
import { useExpose } from '../composables/use-expose'; import { useExpose } from '../composables/use-expose';
// Components
import Picker, { PickerObjectOption } from '../picker';
import { pickerProps } from '../picker/shared'; import { pickerProps } from '../picker/shared';
import Picker from '../picker';
const [createComponent, bem] = createNamespace('area'); const [createComponent, bem] = createNamespace('area');
const EMPTY_CODE = '000000'; const EMPTY_CODE = '000000';
function isOverseaCode(code) { function isOverseaCode(code: string) {
return code[0] === '9'; return code[0] === '9';
} }
function clone(obj) { export type AreaList = {
return JSON.parse(JSON.stringify(obj)); city_list: Record<string, string>;
} county_list: Record<string, string>;
province_list: Record<string, string>;
};
type ColumnType = 'province' | 'county' | 'city';
export default createComponent({ export default createComponent({
props: { props: {
...pickerProps, ...pickerProps,
value: String, value: String,
areaList: { areaList: {
type: Object, type: Object as PropType<AreaList>,
default: () => ({}), default: () => ({}),
}, },
columnsNum: { columnsNum: {
@ -29,11 +50,11 @@ export default createComponent({
default: 3, default: 3,
}, },
isOverseaCode: { isOverseaCode: {
type: Function, type: Function as PropType<(code: string) => boolean>,
default: isOverseaCode, default: isOverseaCode,
}, },
columnsPlaceholder: { columnsPlaceholder: {
type: Array, type: Array as PropType<string[]>,
default: () => [], default: () => [],
}, },
}, },
@ -41,7 +62,8 @@ export default createComponent({
emits: ['change', 'confirm'], emits: ['change', 'confirm'],
setup(props, { emit, slots }) { setup(props, { emit, slots }) {
const pickerRef = ref(); // eslint-disable-next-line
const pickerRef = ref<ComponentPublicInstance<{}, any>>();
const state = reactive({ const state = reactive({
code: props.value, code: props.value,
@ -86,15 +108,14 @@ export default createComponent({
return ''; return '';
}; };
// get list by code const getColumnValues = (type: ColumnType, code?: string) => {
const getList = (type, code) => { let column: PickerObjectOption[] = [];
let result = [];
if (type !== 'province' && !code) { if (type !== 'province' && !code) {
return result; return column;
} }
const list = areaList.value[type]; const list = areaList.value[type];
result = Object.keys(list).map((listCode) => ({ column = Object.keys(list).map((listCode) => ({
code: listCode, code: listCode,
name: list[listCode], name: list[listCode],
})); }));
@ -104,10 +125,10 @@ export default createComponent({
if (type === 'city' && props.isOverseaCode(code)) { if (type === 'city' && props.isOverseaCode(code)) {
code = '9'; code = '9';
} }
result = result.filter((item) => item.code.indexOf(code) === 0); column = column.filter((item) => item.code.indexOf(code!) === 0);
} }
if (placeholderMap.value[type] && result.length) { if (placeholderMap.value[type] && column.length) {
// set columns placeholder // set columns placeholder
let codeFill = ''; let codeFill = '';
if (type === 'city') { if (type === 'city') {
@ -116,17 +137,17 @@ export default createComponent({
codeFill = EMPTY_CODE.slice(4, 6); codeFill = EMPTY_CODE.slice(4, 6);
} }
result.unshift({ column.unshift({
code: code + codeFill, code: code + codeFill,
name: placeholderMap.value[type], name: placeholderMap.value[type],
}); });
} }
return result; return column;
}; };
// get index by code // get index by code
const getIndex = (type, code) => { const getIndex = (type: ColumnType, code: string) => {
let compareNum = code.length; let compareNum = code.length;
if (type === 'province') { if (type === 'province') {
compareNum = props.isOverseaCode(code) ? 1 : 2; compareNum = props.isOverseaCode(code) ? 1 : 2;
@ -137,7 +158,7 @@ export default createComponent({
code = code.slice(0, compareNum); code = code.slice(0, compareNum);
const list = getList( const list = getColumnValues(
type, type,
compareNum > 2 ? code.slice(0, compareNum - 2) : '' compareNum > 2 ? code.slice(0, compareNum - 2) : ''
); );
@ -152,14 +173,10 @@ export default createComponent({
}; };
const setValues = () => { const setValues = () => {
let { code } = state; let code = state.code || getDefaultCode();
if (!code) {
code = getDefaultCode();
}
const picker = pickerRef.value; const picker = pickerRef.value;
const province = getList('province'); const province = getColumnValues('province');
const city = getList('city', code.slice(0, 2)); const city = getColumnValues('city', code.slice(0, 2));
if (!picker) { if (!picker) {
return; return;
@ -176,7 +193,7 @@ export default createComponent({
[{ code }] = city; [{ code }] = city;
} }
picker.setColumnValues(2, getList('county', code.slice(0, 4))); picker.setColumnValues(2, getColumnValues('county', code.slice(0, 4)));
picker.setIndexes([ picker.setIndexes([
getIndex('province', code), getIndex('province', code),
getIndex('city', code), getIndex('city', code),
@ -185,10 +202,10 @@ export default createComponent({
}; };
// parse output columns data // parse output columns data
const parseValues = (values) => { const parseValues = (values: PickerObjectOption[]) => {
return values.map((value, index) => { return values.map((value, index) => {
if (value) { if (value) {
value = clone(value); value = deepClone(value);
if (!value.code || value.name === props.columnsPlaceholder[index]) { if (!value.code || value.name === props.columnsPlaceholder[index]) {
value.code = ''; value.code = '';
@ -202,7 +219,9 @@ export default createComponent({
const getValues = () => { const getValues = () => {
if (pickerRef.value) { if (pickerRef.value) {
const values = pickerRef.value.getValues().filter((value) => !!value); const values = pickerRef.value
.getValues()
.filter((value: PickerObjectOption) => !!value);
return parseValues(values); return parseValues(values);
} }
return []; return [];
@ -246,15 +265,15 @@ export default createComponent({
setValues(); setValues();
}; };
const onChange = (values, index) => { const onChange = (values: PickerObjectOption[], index: number) => {
state.code = values[index].code; state.code = values[index].code;
setValues(); setValues();
const parsedValues = parseValues(pickerRef.value.getValues()); const parsedValues = parseValues(pickerRef.value!.getValues());
emit('change', parsedValues, index); emit('change', parsedValues, index);
}; };
const onConfirm = (values, index) => { const onConfirm = (values: PickerObjectOption[], index: number) => {
setValues(); setValues();
emit('confirm', parseValues(values), index); emit('confirm', parseValues(values), index);
}; };

View File

@ -29,14 +29,14 @@ function getElementTranslateY(element: Element) {
return Number(translateY); return Number(translateY);
} }
export type PickerOption = export type PickerObjectOption = {
| string text?: string;
| {
text: string;
disabled?: boolean; disabled?: boolean;
// for custom filed names // for custom filed names
[key: string]: any; [key: string]: any;
}; };
export type PickerOption = string | PickerObjectOption;
export type PickerObjectColumn = { export type PickerObjectColumn = {
values?: PickerOption[]; values?: PickerOption[];

View File

@ -12,9 +12,10 @@ import { useExpose } from '../composables/use-expose';
// Components // Components
import Loading from '../loading'; import Loading from '../loading';
import Column, { import Column, {
PickerOption,
PickerColumn, PickerColumn,
PickerOption,
PickerObjectColumn, PickerObjectColumn,
PickerObjectOption,
} from './PickerColumn'; } from './PickerColumn';
const [createComponent, bem, t] = createNamespace('picker'); const [createComponent, bem, t] = createNamespace('picker');
@ -27,6 +28,13 @@ export type PickerFieldNames = {
children?: string; children?: string;
}; };
export type {
PickerColumn,
PickerOption,
PickerObjectColumn,
PickerObjectOption,
};
export default createComponent({ export default createComponent({
props: { props: {
...pickerProps, ...pickerProps,

12
src/vue-tsx-shim.d.ts vendored
View File

@ -2,18 +2,22 @@ import 'vue';
type EventHandler = (...args: any[]) => void; type EventHandler = (...args: any[]) => void;
// TODO
// should be removed after Vue supported component events typing
// see: https://github.com/vuejs/vue-next/issues/1553
// https://github.com/vuejs/vue-next/issues/3029
declare module 'vue' { declare module 'vue' {
interface ComponentCustomProps { interface ComponentCustomProps {
role?: string; role?: string;
tabindex?: number; tabindex?: number;
// should be removed after Vue supported component events typing
// see: https://github.com/vuejs/vue-next/issues/1553
// https://github.com/vuejs/vue-next/issues/3029
onBlur?: EventHandler;
onFocus?: EventHandler;
onInput?: EventHandler;
onClick?: EventHandler; onClick?: EventHandler;
onCancel?: EventHandler;
onClosed?: EventHandler; onClosed?: EventHandler;
onChange?: EventHandler; onChange?: EventHandler;
onToggle?: EventHandler; onToggle?: EventHandler;
onConfirm?: EventHandler;
onClickStep?: EventHandler; onClickStep?: EventHandler;
} }
} }