mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-06 03:57:59 +08:00
refactor(Area): refactor with composition api
This commit is contained in:
parent
9301092f20
commit
c54025ce83
@ -1,15 +1,20 @@
|
||||
import { createNamespace } from '../utils';
|
||||
import { ref, watch, computed, reactive, nextTick, onMounted } from 'vue';
|
||||
import { createNamespace, pick } from '../utils';
|
||||
import { pickerProps } from '../picker/shared';
|
||||
import Picker from '../picker';
|
||||
|
||||
const [createComponent, bem] = createNamespace('area');
|
||||
|
||||
const PLACEHOLDER_CODE = '000000';
|
||||
const EMPTY_CODE = '000000';
|
||||
|
||||
function isOverseaCode(code) {
|
||||
return code[0] === '9';
|
||||
}
|
||||
|
||||
function clone(obj) {
|
||||
return JSON.parse(JSON.stringify(obj));
|
||||
}
|
||||
|
||||
export default createComponent({
|
||||
props: {
|
||||
...pickerProps,
|
||||
@ -34,79 +39,60 @@ export default createComponent({
|
||||
|
||||
emits: ['change', 'confirm'],
|
||||
|
||||
data() {
|
||||
return {
|
||||
code: this.value,
|
||||
columns: [{ values: [] }, { values: [] }, { values: [] }],
|
||||
};
|
||||
},
|
||||
setup(props, { emit, slots }) {
|
||||
const pickerRef = ref(null);
|
||||
|
||||
computed: {
|
||||
province() {
|
||||
return this.areaList.province_list || {};
|
||||
},
|
||||
const state = reactive({
|
||||
code: ref(props.value),
|
||||
columns: reactive([{ values: [] }, { values: [] }, { values: [] }]),
|
||||
});
|
||||
|
||||
city() {
|
||||
return this.areaList.city_list || {};
|
||||
},
|
||||
|
||||
county() {
|
||||
return this.areaList.county_list || {};
|
||||
},
|
||||
|
||||
displayColumns() {
|
||||
return this.columns.slice(0, +this.columnsNum);
|
||||
},
|
||||
|
||||
placeholderMap() {
|
||||
const areaList = computed(() => {
|
||||
const { areaList } = props;
|
||||
return {
|
||||
province: this.columnsPlaceholder[0] || '',
|
||||
city: this.columnsPlaceholder[1] || '',
|
||||
county: this.columnsPlaceholder[2] || '',
|
||||
province: areaList.province_list || {},
|
||||
city: areaList.city_list || {},
|
||||
county: areaList.county_list || {},
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
pickerSlots() {
|
||||
return ['title', 'columns-top', 'columns-bottom'].reduce((slots, key) => {
|
||||
slots[key] = this.$slots[key];
|
||||
return slots;
|
||||
}, {});
|
||||
},
|
||||
},
|
||||
const placeholderMap = computed(() => {
|
||||
const { columnsPlaceholder } = props;
|
||||
return {
|
||||
province: columnsPlaceholder[0] || '',
|
||||
city: columnsPlaceholder[1] || '',
|
||||
county: columnsPlaceholder[2] || '',
|
||||
};
|
||||
});
|
||||
|
||||
watch: {
|
||||
value(val) {
|
||||
this.code = val;
|
||||
this.setValues();
|
||||
},
|
||||
const getDefaultCode = () => {
|
||||
if (props.columnsPlaceholder.length) {
|
||||
return EMPTY_CODE;
|
||||
}
|
||||
|
||||
areaList: {
|
||||
deep: true,
|
||||
handler() {
|
||||
this.setValues();
|
||||
},
|
||||
},
|
||||
const { county, city } = areaList.value;
|
||||
|
||||
columnsNum() {
|
||||
this.$nextTick(() => {
|
||||
this.setValues();
|
||||
});
|
||||
},
|
||||
},
|
||||
const countyCodes = Object.keys(county);
|
||||
if (countyCodes[0]) {
|
||||
return countyCodes[0];
|
||||
}
|
||||
|
||||
mounted() {
|
||||
this.setValues();
|
||||
},
|
||||
const cityCodes = Object.keys(city);
|
||||
if (cityCodes[0]) {
|
||||
return cityCodes[0];
|
||||
}
|
||||
|
||||
return '';
|
||||
};
|
||||
|
||||
methods: {
|
||||
// get list by code
|
||||
getList(type, code) {
|
||||
const getList = (type, code) => {
|
||||
let result = [];
|
||||
if (type !== 'province' && !code) {
|
||||
return result;
|
||||
}
|
||||
|
||||
const list = this[type];
|
||||
const list = areaList.value[type];
|
||||
result = Object.keys(list).map((listCode) => ({
|
||||
code: listCode,
|
||||
name: list[listCode],
|
||||
@ -114,38 +100,37 @@ export default createComponent({
|
||||
|
||||
if (code) {
|
||||
// oversea code
|
||||
if (this.isOverseaCode(code) && type === 'city') {
|
||||
if (type === 'city' && props.isOverseaCode(code)) {
|
||||
code = '9';
|
||||
}
|
||||
|
||||
result = result.filter((item) => item.code.indexOf(code) === 0);
|
||||
}
|
||||
|
||||
if (this.placeholderMap[type] && result.length) {
|
||||
if (placeholderMap.value[type] && result.length) {
|
||||
// set columns placeholder
|
||||
let codeFill = '';
|
||||
if (type === 'city') {
|
||||
codeFill = PLACEHOLDER_CODE.slice(2, 4);
|
||||
codeFill = EMPTY_CODE.slice(2, 4);
|
||||
} else if (type === 'county') {
|
||||
codeFill = PLACEHOLDER_CODE.slice(4, 6);
|
||||
codeFill = EMPTY_CODE.slice(4, 6);
|
||||
}
|
||||
|
||||
result.unshift({
|
||||
code: `${code}${codeFill}`,
|
||||
name: this.placeholderMap[type],
|
||||
code: code + codeFill,
|
||||
name: placeholderMap.value[type],
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
};
|
||||
|
||||
// get index by code
|
||||
getIndex(type, code) {
|
||||
const getIndex = (type, code) => {
|
||||
let compareNum = type === 'province' ? 2 : type === 'city' ? 4 : 6;
|
||||
const list = this.getList(type, code.slice(0, compareNum - 2));
|
||||
const list = getList(type, code.slice(0, compareNum - 2));
|
||||
|
||||
// oversea code
|
||||
if (this.isOverseaCode(code) && type === 'province') {
|
||||
if (props.isOverseaCode(code) && type === 'province') {
|
||||
compareNum = 1;
|
||||
}
|
||||
|
||||
@ -158,68 +143,17 @@ export default createComponent({
|
||||
}
|
||||
|
||||
return 0;
|
||||
},
|
||||
|
||||
// parse output columns data
|
||||
parseOutputValues(values) {
|
||||
return values.map((value, index) => {
|
||||
// save undefined value
|
||||
if (!value) return value;
|
||||
|
||||
value = JSON.parse(JSON.stringify(value));
|
||||
|
||||
if (!value.code || value.name === this.columnsPlaceholder[index]) {
|
||||
value.code = '';
|
||||
value.name = '';
|
||||
}
|
||||
|
||||
return value;
|
||||
});
|
||||
},
|
||||
|
||||
onChange(values, index) {
|
||||
const { picker } = this.$refs;
|
||||
this.code = values[index].code;
|
||||
this.setValues();
|
||||
|
||||
const parsedValues = this.parseOutputValues(picker.getValues());
|
||||
this.$emit('change', parsedValues, index);
|
||||
},
|
||||
|
||||
onConfirm(values, index) {
|
||||
values = this.parseOutputValues(values);
|
||||
this.setValues();
|
||||
this.$emit('confirm', values, index);
|
||||
},
|
||||
|
||||
getDefaultCode() {
|
||||
if (this.columnsPlaceholder.length) {
|
||||
return PLACEHOLDER_CODE;
|
||||
}
|
||||
|
||||
const countyCodes = Object.keys(this.county);
|
||||
if (countyCodes[0]) {
|
||||
return countyCodes[0];
|
||||
}
|
||||
|
||||
const cityCodes = Object.keys(this.city);
|
||||
if (cityCodes[0]) {
|
||||
return cityCodes[0];
|
||||
}
|
||||
|
||||
return '';
|
||||
},
|
||||
|
||||
setValues() {
|
||||
let { code } = this;
|
||||
};
|
||||
|
||||
const setValues = () => {
|
||||
let { code } = state;
|
||||
if (!code) {
|
||||
code = this.getDefaultCode();
|
||||
code = getDefaultCode();
|
||||
}
|
||||
|
||||
const { picker } = this.$refs;
|
||||
const province = this.getList('province');
|
||||
const city = this.getList('city', code.slice(0, 2));
|
||||
const picker = pickerRef.value;
|
||||
const province = getList('province');
|
||||
const city = getList('city', code.slice(0, 2));
|
||||
|
||||
if (!picker) {
|
||||
return;
|
||||
@ -231,30 +165,45 @@ export default createComponent({
|
||||
if (
|
||||
city.length &&
|
||||
code.slice(2, 4) === '00' &&
|
||||
!this.isOverseaCode(code)
|
||||
!props.isOverseaCode(code)
|
||||
) {
|
||||
[{ code }] = city;
|
||||
}
|
||||
|
||||
picker.setColumnValues(2, this.getList('county', code.slice(0, 4)));
|
||||
picker.setColumnValues(2, getList('county', code.slice(0, 4)));
|
||||
picker.setIndexes([
|
||||
this.getIndex('province', code),
|
||||
this.getIndex('city', code),
|
||||
this.getIndex('county', code),
|
||||
getIndex('province', code),
|
||||
getIndex('city', code),
|
||||
getIndex('county', code),
|
||||
]);
|
||||
},
|
||||
};
|
||||
|
||||
getValues() {
|
||||
const { picker } = this.$refs;
|
||||
let getValues = picker
|
||||
? picker.getValues().filter((value) => !!value)
|
||||
: [];
|
||||
getValues = this.parseOutputValues(getValues);
|
||||
return getValues;
|
||||
},
|
||||
// parse output columns data
|
||||
const parseValues = (values) => {
|
||||
return values.map((value, index) => {
|
||||
if (value) {
|
||||
value = clone(value);
|
||||
|
||||
getArea() {
|
||||
const values = this.getValues();
|
||||
if (!value.code || value.name === props.columnsPlaceholder[index]) {
|
||||
value.code = '';
|
||||
value.name = '';
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
});
|
||||
};
|
||||
|
||||
const getValues = () => {
|
||||
if (pickerRef.value) {
|
||||
const values = pickerRef.value.getValues().filter((value) => !!value);
|
||||
return parseValues(values);
|
||||
}
|
||||
return [];
|
||||
};
|
||||
|
||||
const getArea = () => {
|
||||
const values = getValues();
|
||||
const area = {
|
||||
code: '',
|
||||
country: '',
|
||||
@ -274,7 +223,7 @@ export default createComponent({
|
||||
? validValues[validValues.length - 1].code
|
||||
: '';
|
||||
|
||||
if (this.isOverseaCode(area.code)) {
|
||||
if (props.isOverseaCode(area.code)) {
|
||||
area.country = names[1] || '';
|
||||
area.province = names[2] || '';
|
||||
} else {
|
||||
@ -284,33 +233,73 @@ export default createComponent({
|
||||
}
|
||||
|
||||
return area;
|
||||
},
|
||||
};
|
||||
|
||||
// @exposed-api
|
||||
reset(code) {
|
||||
this.code = code || '';
|
||||
this.setValues();
|
||||
},
|
||||
},
|
||||
const reset = (newCode = '') => {
|
||||
state.code = newCode;
|
||||
setValues();
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Picker
|
||||
v-slots={this.pickerSlots}
|
||||
ref="picker"
|
||||
class={bem()}
|
||||
valueKey="name"
|
||||
title={this.title}
|
||||
loading={this.loading}
|
||||
columns={this.displayColumns}
|
||||
itemHeight={this.itemHeight}
|
||||
swipeDuration={this.swipeDuration}
|
||||
visibleItemCount={this.visibleItemCount}
|
||||
cancelButtonText={this.cancelButtonText}
|
||||
confirmButtonText={this.confirmButtonText}
|
||||
onChange={this.onChange}
|
||||
onConfirm={this.onConfirm}
|
||||
/>
|
||||
const onChange = (values, index) => {
|
||||
state.code = values[index].code;
|
||||
setValues();
|
||||
|
||||
const parsedValues = parseValues(pickerRef.value.getValues());
|
||||
emit('change', parsedValues, index);
|
||||
};
|
||||
|
||||
const onConfirm = (values, index) => {
|
||||
values = parseValues(values);
|
||||
setValues();
|
||||
emit('confirm', values, index);
|
||||
};
|
||||
|
||||
onMounted(setValues);
|
||||
|
||||
watch(
|
||||
() => props.value,
|
||||
(value) => {
|
||||
state.code = value;
|
||||
setValues();
|
||||
}
|
||||
);
|
||||
|
||||
watch(() => props.areaList, setValues, { deep: true });
|
||||
|
||||
watch(
|
||||
() => props.columnsNum,
|
||||
() => {
|
||||
nextTick(setValues);
|
||||
}
|
||||
);
|
||||
|
||||
return (vm) => {
|
||||
// @exposed-api
|
||||
vm.reset = reset;
|
||||
vm.getArea = getArea;
|
||||
|
||||
const columns = state.columns.slice(0, +props.columnsNum);
|
||||
|
||||
return (
|
||||
<Picker
|
||||
v-slots={pick(slots, ['title', 'columns-top', 'columns-bottom'])}
|
||||
ref={pickerRef}
|
||||
class={bem()}
|
||||
columns={columns}
|
||||
valueKey="name"
|
||||
onChange={onChange}
|
||||
onConfirm={onConfirm}
|
||||
{...pick(props, [
|
||||
'title',
|
||||
'loading',
|
||||
'itemHeight',
|
||||
'swipeDuration',
|
||||
'visibleItemCount',
|
||||
'cancelButtonText',
|
||||
'confirmButtonText',
|
||||
])}
|
||||
/>
|
||||
);
|
||||
};
|
||||
},
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user