在用uniapp做h5页面时,需要一个类似京东的地址选择弹框组件,故基于uView自己动手封装了一个(如若需要做回显,可以绑定v-model,然后监听value的变化;或者直接在调用open方法时从外部传入参数过来,请自行更改)。
组件region-selection页面如下:
<template>
<u-popup :show="show" :round="10" mode="bottom" @close="close" :closeable="true">
<view style="height: 500px">
<view><u--text text="所在地区" margin="30rpx 0" size="18" bold align="center"></u--text></view>
<!-- 当前选中的地区 -->
<view class="hasSelected">
<view v-for="(item, index) in result" :key="index" :class="index === current ? 'item active' : 'item'"
@click="resultChange(item, index)">{{ item.label }}</view>
</view>
<!-- 地区数据展示区 -->
<view>
<u-list showScrollbar height="380px" v-if="!isFail">
<u-list-item v-for="(item, index) in list" :key="index">
<u-cell @click="listChange" :name="JSON.stringify(item)">
<view slot="title">
<u--text :suffixIcon="result[current].value === item.dmbm ? 'checkbox-mark' : ''"
iconStyle="font-size: 25px;color:#f56c6c;margin-left:30rpx;" :text="item.dmmc"
size="18" :bold="result[current].value === item.dmbm"></u--text>
</view>
</u-cell>
</u-list-item>
</u-list>
<u-empty v-else mode="data" text="请求失败">
<u-button @click="refresh" type="primary" class="mt-20">重新请求</u-button>
</u-empty>
</view>
</view>
</u-popup>
</template>
<script>
/**
* @Date 2024-03-01
* @Description 基于uView(https://www.uviewui.com/components/intro.html)组件封装的地区选择组件
*/
import { getXzqhList } from '@/common/api/common';
export default {
name: 'region-selection',
props: {
// value: {
// type: Array,
// required: true
// }
},
watch: {
// value: {
// immediate: true,
// handler(newValue, oldValue) {
// if (newValue && newValue.length > 0) {
// this.result = newValue;
// } else {
// this.result = [{ label: '请选择', value: '' }]
// }
// }
// }
},
data() {
return {
show: false,
current: 0, //当前在第几层
result: [{ label: '请选择', value: '', sjdm: '' }],
list: [],
isFail: false //控制是否请求失败
};
},
methods: {
//打开时展示第一层数据
open() {
this.show = true;
this.current = 0;
getXzqhList()
.then((res) => {
this.isFail = false;
this.list = res.data || [];
})
.catch(() => {
this.isFail = true;
});
},
//点击城市列表
listChange({ name }) {
try {
const item = JSON.parse(name);
this.result.splice(this.current, 1, { label: item.dmmc, value: item.dmbm, sjdm: item.sjdmbm });
getXzqhList({ sjdmbm: item.dmbm })
.then((res) => {
this.isFail = false;
this.list = res.data;
if (this.list && this.list.length > 0) {
//如果还有下一级城市
this.result.splice(this.current + 1);
this.current++;
this.result.splice(this.current, 1, { label: '请选择', value: '', sjdm: '' });
} else {
//没有下一级城市了
this.show = false;
this.$emit('ok', this.result);
// this.$emit('input', JSON.stringify(this.result));
}
})
.catch(() => {
this.isFail = true;
});
} catch (e) { }
},
//点击顶部已选择的城市
resultChange(item, index) {
if (item.value) {
this.current = index;
getXzqhList({ sjdmbm: item.sjdm })
.then((res) => {
this.isFail = false;
this.list = res.data;
})
.catch(() => {
this.isFail = true;
});
}
},
//重新加载
refresh() {
getXzqhList({ sjdmbm: this.result[this.current].sjdm })
.then((res) => {
this.isFail = false;
this.list = res.data;
})
.catch(() => {
this.isFail = true;
});
},
close() {
this.show = false;
}
}
};
</script>
<style scoped lang="scss">
.hasSelected {
padding-bottom: 20rpx;
border-bottom: 1px solid #4b4848;
.item {
font-size: 20px;
display: inline;
padding: 0 10rpx;
}
.active {
color: #f56c6c;
}
}
</style>
页面中使用:
<template>
<packPage>
<packHeader slot="gHeader" center title="新增地址"></packHeader>
<view slot="gBody" class="content">
<view class="contentWrap">
<u--form labelPosition="left" :model="form" :rules="formRules" labelWidth="90" ref="formRef">
<u-gap height="8" bgColor="#f6f6f8"></u-gap>
<u-form-item label="所在地区" prop="xzdxzqhName" required @click="openRegion()" borderBottom>
<u--input v-model="form.xzdxzqhName" border="none" placeholder="请选择地区" readonly></u--input>
<u-icon name="arrow-right" slot="right"></u-icon>
</u-form-item>
<view style="padding: 5px 10px 0 7px">
<span style="color: #f56c6c">*</span>
<span>详细地址</span>
</view>
<u-form-item label="" prop="pic1" borderBottom labelWidth="0">
<u--textarea v-model="form.xxdz" placeholder="请输入详细地址,如小区、写字楼、门牌号等"></u--textarea>
</u-form-item>
</u--form>
<view style="width: 60%; display: flex; margin: 0 auto; padding: 50rpx 0">
<u-button @click="submit" type="primary" shape="circle">提交</u-button>
</view>
</view>
</view>
<!--选择住址-->
<regionSelection ref="regionSelect" @ok="confirmRegion"></regionSelection>
</packPage>
</template>
<script>
import regionSelection from '@/components/region-selection';
export default {
components:{regionSelection},
data() {
return {
form: {}
};
},
methods: {
openRegion(){
this.$refs.regionSelect.open();
},
confirmRegion(data){
let temp='';
data.map(i=>temp+=i.label)
this.$set(this.form, 'xzdxzqhName', temp);
}
}
};
</script>
地址选择组件内部只调用了一个接口,通过传入上级城市代码一层一层调用,第一层接口返回格式如下:
{
"code": 200,
"msg": "操作成功",
"data": [
{
"dmbm": "494",
"xzqhdm": "110000",
"dmmc": "北京市",
"sm": "北京市",
"dsm": null,
"xqm": null,
"sjdmbm": "0"
},
{
"dmbm": "2955",
"xzqhdm": "120000",
"dmmc": "天津市",
"sm": "天津市",
"dsm": null,
"xqm": null,
"sjdmbm": "0"
},
{
"dmbm": "237",
"xzqhdm": "130000",
"dmmc": "河北省",
"sm": "河北省",
"dsm": null,
"xqm": null,
"sjdmbm": "0"
},
{
"dmbm": "1063",
"xzqhdm": "140000",
"dmmc": "山西省",
"sm": "山西省",
"dsm": null,
"xqm": null,
"sjdmbm": "0"
},
]
}
效果图如下所示:
基于uView封装的地址选择弹框组件