From 749e4ae73b9c07265e81237493b5e7d37afc6255 Mon Sep 17 00:00:00 2001 From: chenjiahan Date: Thu, 24 Sep 2020 17:19:14 +0800 Subject: [PATCH] refactor(AddressEdit): refactor with composition api --- src/address-edit/index.js | 466 +++++++++++++++++++------------------- 1 file changed, 236 insertions(+), 230 deletions(-) diff --git a/src/address-edit/index.js b/src/address-edit/index.js index 9acca72ee..24770c47e 100644 --- a/src/address-edit/index.js +++ b/src/address-edit/index.js @@ -1,7 +1,12 @@ +import { h, ref, watch, computed, nextTick, reactive } from 'vue'; + // Utils import { createNamespace, isObject } from '../utils'; import { isMobile } from '../utils/validate/mobile'; +// Composition +import { useExpose } from '../composition/use-expose'; + // Components import Area from '../area'; import Cell from '../cell'; @@ -94,8 +99,10 @@ export default createComponent({ 'change-default', ], - data() { - return { + setup(props, { emit, slots }) { + const areaRef = ref(); + + const state = reactive({ data: {}, showAreaPopup: false, detailFocused: false, @@ -106,16 +113,14 @@ export default createComponent({ postalCode: '', addressDetail: '', }, - }; - }, + }); - computed: { - areaListLoaded() { - return isObject(this.areaList) && Object.keys(this.areaList).length; - }, + const areaListLoaded = computed( + () => isObject(props.areaList) && Object.keys(props.areaList).length + ); - areaText() { - const { country, province, city, county, areaCode } = this.data; + const areaText = computed(() => { + const { country, province, city, county, areaCode } = state.data; if (areaCode) { const arr = [country, province, city, county]; if (province && province === city) { @@ -124,103 +129,34 @@ export default createComponent({ return arr.filter((text) => text).join('/'); } return ''; - }, + }); // hide bottom field when use search && detail get focused - hideBottomFields() { - const { searchResult } = this; - return searchResult && searchResult.length && this.detailFocused; - }, - }, + const hideBottomFields = computed(() => { + const { searchResult } = props; + return searchResult && searchResult.length && state.detailFocused; + }); - watch: { - addressInfo: { - handler(val) { - this.data = { - ...defaultData, - ...val, - }; - - this.setAreaCode(val.areaCode); - }, - deep: true, - immediate: true, - }, - - areaList() { - this.setAreaCode(this.data.areaCode); - }, - }, - - methods: { - onFocus(key) { - this.errorInfo[key] = ''; - this.detailFocused = key === 'addressDetail'; - this.$emit('focus', key); - }, - - onChangeDetail(val) { - this.data.addressDetail = val; - this.$emit('change-detail', val); - }, - - onAreaConfirm(values) { - values = values.filter((value) => !!value); - - if (values.some((value) => !value.code)) { - Toast(t('areaEmpty')); - return; - } - - this.showAreaPopup = false; - this.assignAreaValues(); - this.$emit('change-area', values); - }, - - assignAreaValues() { - const { area } = this.$refs; - - if (area) { - const detail = area.getArea(); + const assignAreaValues = () => { + if (areaRef.value) { + const detail = areaRef.value.getArea(); detail.areaCode = detail.code; delete detail.code; - Object.assign(this.data, detail); + Object.assign(state.data, detail); } - }, + }; - onSave() { - const items = ['name', 'tel']; + const onFocus = (key) => { + state.errorInfo[key] = ''; + state.detailFocused = key === 'addressDetail'; + emit('focus', key); + }; - if (this.showArea) { - items.push('areaCode'); - } + const getErrorMessage = (key) => { + const value = String(state.data[key] || '').trim(); - if (this.showDetail) { - items.push('addressDetail'); - } - - if (this.showPostal) { - items.push('postalCode'); - } - - const isValid = items.every((item) => { - const msg = this.getErrorMessage(item); - if (msg) { - this.errorInfo[item] = msg; - } - return !msg; - }); - - if (isValid && !this.isSaving) { - this.$emit('save', this.data); - } - }, - - getErrorMessage(key) { - const value = String(this.data[key] || '').trim(); - - if (this.validator) { - const message = this.validator(key, value); + if (props.validator) { + const message = props.validator(key, value); if (message) { return message; } @@ -230,63 +166,106 @@ export default createComponent({ case 'name': return value ? '' : t('nameEmpty'); case 'tel': - return this.telValidator(value) ? '' : t('telInvalid'); + return props.telValidator(value) ? '' : t('telInvalid'); case 'areaCode': return value ? '' : t('areaEmpty'); case 'addressDetail': return value ? '' : t('addressEmpty'); case 'postalCode': - return value && !this.postalValidator(value) ? t('postalEmpty') : ''; + return value && !props.postalValidator(value) ? t('postalEmpty') : ''; } - }, + }; - onDelete() { + const onSave = () => { + const items = ['name', 'tel']; + + if (props.showArea) { + items.push('areaCode'); + } + + if (props.showDetail) { + items.push('addressDetail'); + } + + if (props.showPostal) { + items.push('postalCode'); + } + + const isValid = items.every((item) => { + const msg = getErrorMessage(item); + if (msg) { + state.errorInfo[item] = msg; + } + return !msg; + }); + + if (isValid && !props.isSaving) { + emit('save', state.data); + } + }; + + const onChangeDetail = (val) => { + state.data.addressDetail = val; + emit('change-detail', val); + }; + + const onAreaConfirm = (values) => { + values = values.filter((value) => !!value); + + if (values.some((value) => !value.code)) { + Toast(t('areaEmpty')); + return; + } + + state.showAreaPopup = false; + assignAreaValues(); + emit('change-area', values); + }; + + const onDelete = () => { Dialog.confirm({ title: t('confirmDelete'), }) .then(() => { - this.$emit('delete', this.data); + emit('delete', state.data); }) .catch(() => { - this.$emit('cancel-delete', this.data); + emit('cancel-delete', state.data); }); - }, + }; // get values of area component - getArea() { - return this.$refs.area ? this.$refs.area.getValues() : []; - }, + const getArea = () => (areaRef.value ? areaRef.value.getValues() : []); // set area code to area component - setAreaCode(code) { - this.data.areaCode = code || ''; + const setAreaCode = (code) => { + state.data.areaCode = code || ''; if (code) { - this.$nextTick(this.assignAreaValues); + nextTick(assignAreaValues); } - }, + }; - // @exposed-api - setAddressDetail(value) { - this.data.addressDetail = value; - }, - - onDetailBlur() { + const onDetailBlur = () => { // await for click search event setTimeout(() => { - this.detailFocused = false; + state.detailFocused = false; }); - }, + }; - genSetDefaultCell(h) { - if (this.showSetDefault) { + const setAddressDetail = (value) => { + state.data.addressDetail = value; + }; + + const renderSetDefaultCell = () => { + if (props.showSetDefault) { const slots = { 'right-icon': () => ( { - this.$emit('change-default', event); + emit('change-default', event); }} /> ), @@ -295,7 +274,7 @@ export default createComponent({ return ( () => this.onFocus(name); + useExpose({ + getArea, + setAddressDetail, + }); - return ( -
-
- - - { - this.$emit('click-area'); - this.showAreaPopup = !disableArea; - }} - /> - { - this.$emit('select-search', event); - }} - /> - {this.showPostal && ( + watch( + () => props.areaList, + () => { + setAreaCode(state.data.areaCode); + } + ); + + watch( + () => props.addressInfo, + (value) => { + state.data = { + ...defaultData, + ...value, + }; + setAreaCode(value.areaCode); + }, + { + deep: true, + immediate: true, + } + ); + + return () => { + const { data, errorInfo } = state; + const { disableArea } = props; + + return ( +
+
onFocus('name')} /> - )} - {this.$slots.default?.()} -
- {this.genSetDefaultCell(h)} -
-
+ {renderSetDefaultCell()} +
+ + { + state.showAreaPopup = false; + }} + /> +
- - { - this.showAreaPopup = false; - }} - /> - -
- ); + ); + }; }, });