vue自定义省市区街道选择
vue
中自定义选择省、市、区、街道
功能,如不需要街道
,可自行删除。这里相关代码没有封装,可自行操作。供参考,欢迎指点。
说明:
- 所有数据由
后端
返回。【见末尾效果图】 - 在
created
生命周期中获取省
数据,当用户点击某省
得到当前id【父级id】
并保存。 - 根据
父级id
获取市
数据。由此类推。
文章目录
- vue自定义省市区街道选择
- 效果图
- template
- 实现步骤
- 初始化数据
- 选择省市区街道事件
- 点击省市区标题事件
- 获取地址列表数据
- style
- 后端返回数据效果图
- 数据库结构效果图
效果图
template
由于当时项目结合
vant
组件库,这里底部弹窗
应用组件库
<!-- 选择省市区 -->
<div class="van-cell van-field address">
<div class="van-cell__title van-field__label">门店地址</div>
<div class="tips" @click="clickProvincesTap">
<span :class="chooseCity != '请选择' ? 'c' : ''">{{chooseCity == '请选择' ? '请选择' : chooseCity}}</span>
<img src="../../assets/images/icon/arrow_r.png" alt="">
</div>
</div>
<!-- 列表展示 -->
<section class="showAddressList">
<van-action-sheet v-model="showList">
<div class="titleBox">
<p></p>
<p class="title">经营场所地址</p>
<p class="confirm" @click="showList = false">取消</p>
</div>
<!-- 省市区街道的标题 -->
<div class="chooseList">
<div class="showAddress bd">
<div class="showArea">
<p class="tipTxt" @click="chooseProvince" v-show='tit1'>{{chooseTit1}}</p>
<p class="tipTxt" @click="chooseCitys" v-show='tit2'>{{chooseTit2}}</p>
<p class="tipTxt" @click="chooseArea" v-show='tit3'>{{chooseTit3}}</p>
<p class="tipTxt" v-show='tit4'>{{chooseTit4}}</p>
</div>
</div>
<!-- 省市区列表 --->
<div class="addressList">
<ul v-show="showProvince">
<li v-for="(item, index) in provinceL" :key="item.id" @click="getProvince(item, index)">
<div class="items">
<div>{{item.name}}</div>
<div class="checkIcon" :class="{showIcon: activeIcon1 === index}">
<img src="../../assets/images/icon/inquire_ico_check.png" alt="">
</div>
</div>
</li>
</ul>
<ul v-show="showCity">
<li v-for="(item, index) in cityL" :key="item.id" @click="getCity(item, index)">
<div class="items">
<div>{{item.name}}</div>
<div class="checkIcon" :class="{showIcon: activeIcon2 === index}">
<img src="../../assets/images/icon/inquire_ico_check.png" alt="">
</div>
</div>
</li>
</ul>
<ul v-show="showArea">
<li v-for="(item, index) in areaL" :key="item.id" @click="getArea(item, index)">
<div class="items">
<div>{{item.name}}</div>
<div class="checkIcon" :class="{showIcon: activeIcon3 === index}">
<img src="../../assets/images/icon/inquire_ico_check.png" alt="">
</div>
</div>
</li>
</ul>
<ul v-show="showStreet">
<li v-for="(item, index) in streetL" :key="item.id" @click="getStreet(item, index)">
<div class="items">
<div>{{item.name}}</div>
<div class="checkIcon" :class="{showIcon: activeIcon4 === index}">
<img src="../../assets/images/icon/inquire_ico_check.png" alt="">
</div>
</div>
</li>
</ul>
</div>
</div>
</van-action-sheet>
</section>
实现步骤
初始化数据
<script>
export default {
name: "addBiz",
data() {
return {
chooseCity: "请选择",
provinceL: [], //省数据列表
cityL: [],
areaL: [],
streetL: [],
showProvince: true, //是否显示模块
showCity: false,
showArea: false,
showStreet: false,
chooseTit1: "请选择省", //占位
chooseTit2: "请选择市",
chooseTit3: "请选择区",
chooseTit4: "请选择街道",
tit1: true, //切换标题
tit2: false,
tit3: false,
tit4: false,
province: "", //当前选择值
Nextcity: "",
district: "",
street: "",
currentType: 1, //当前操作类型 1:省:,2:市,3:区,4:街道
parentId: 1, //父级id
currentAdsId: '', //当前选择地址id
showList: false, //显示地址列表
activeIcon1: -1, //省 icon状态
activeIcon2: -1,
activeIcon3: -1,
activeIcon4: -1,
}
},
created() {
// 获取地址省列表
this.addressList();
},
methods: {
// 点击选择 省市区 展示弹窗
clickProvincesTap() {
this.showList = true;
},
}
}
</script>
选择省市区街道事件
根据当前操作事件得到
id
获取对应数据,修改相关数据状态。
//当用户点击某个省事件 根据省的id获取市
getProvince(item, index) {
this.province = item.name;
this.chooseTit1 = item.name;
this.activeIcon1 = index; //当前选中icon
this.currentType = 2;
this.currentAdsId = item.id;
this.parentId = item.id;
//获取地址列表
this.addressList();
},
//当用户点击某个市事件 根据市的id获取区
getCity(item, index) {
this.Nextcity = item.name;
this.chooseTit2 = item.name;
this.activeIcon3 = -1; //重置icon状态
this.activeIcon2 = index; //当前选中icon
this.currentType = 3;
this.currentAdsId = item.id;
this.parentId = item.id;
//获取地址列表
this.addressList();
},
//当用户点击某个区事件 根据区的id获取街道
getArea(item, index) {
this.district = item.name;
this.chooseTit3 = item.name;
this.activeIcon4 = -1;
this.activeIcon3 = index;
this.currentType = 4;
this.currentAdsId = item.id;
this.parentId = item.id;
//获取地址列表
this.addressList();
},
//用户点击镇,隐藏弹窗
getStreet(item, index) {
this.street = item.name;
this.chooseTit4 = item.name;
this.currentAdsId = item.id;
this.activeIcon4 = index;
//获取地址列表
this.isShowList();
},
//弹窗消失 保存当前选择值
isShowList() {
var totalCity = `${this.province}${this.Nextcity}${this.district}${this.street}`;
this.chooseCity = totalCity;
this.showList = false;
},
点击省市区标题事件
点击
省市区
标题时,控制显示/隐藏相关状态
//点击省市区标题显示/隐藏相关内容 形成回退效果
chooseProvince() {
this.showProvince = true;
this.showCity = false;
this.showArea = false;
this.showStreet = false;
this.activeIcon2 = -1; //重置
},
chooseCitys() { //选择市
this.showProvince = false;
this.showCity = true;
this.showArea = false;
this.showStreet = false;
this.activeIcon3 = -1; //重置
},
chooseArea() { //选择区
this.showProvince = false;
this.showCity = false;
this.showArea = true;
this.showStreet = false;
},
获取地址列表数据
根据
父级id
查询数据,数据请求成功后,根据当前类型修改状态、重置值。
/**
* 获取地址列表
*/
addressList() {
this.loadings('加载中...');
let that = this;
let params = {
type: that.currentType, //当前操作类型
parent_id: that.parentId //父级id
};
this.axios.addressList(params).then(res => {
that.$toast.clear();
let datas = res.data;
if (parseInt(datas.code) != 200) {
that.$toast(datas.msg);
return;
}
//处理数据
that.handleByType(datas.data);
});
},
//根据当前操作类型处理数据
handleByType(datas) {
if(datas.length == 0) {
this.isShowList();
return;
}
switch(this.currentType) {
case 1: //省
this.provinceL = datas;
break;
case 2: //市
this.cityL = datas;
this.citySelected = this.cityL[0].id;
this.showProvince = false;
this.showCity = true;
this.tit2 = true;
this.areaL = [];
break;
case 3: //区
this.areaL = datas;
this.areaSelected = this.areaL[0].id;
this.showCity = false;
this.showArea = true;
this.tit3 = true;
this.streetL = [];
break;
case 4: //街道
this.streetL = datas;
this.streetSelected = this.streetL[0].id;
this.showCity = false;
this.showArea = false;
this.showStreet = true;
this.tit4 = true;
break;
}
}
style
px
最终转换为rem
单位值,根据需要修改
.showAddressList {
.titleBox {
@include wh(100%, 108px);
@include sc(32px, $fc9);
@include fcc;
@include bg(#F4F4F4);
padding: 0 30px;
>p {
flex: 1;
}
.title {
@include sc(36px, $fc);
text-align: center;
}
.confirm {
color: $main;
text-align: right;
}
}
.chooseList {
@include sc(32px, $fc);
.showAddress {
@include fc;
padding: 30px;
.showArea {
@include fc;
p {
margin-right: 30px;
}
}
.tipTxt {
@include sc(32px, $fc9);
position: relative;
&::after {
content: '';
@include cl;
bottom: -28px;
@include wh(94px, 4px);
@include bg($main);
@include borderRadius(2px);
transition: all 0.1s;
}
}
}
.bd {
&::after {
border-color: #E5E5E5;
left: 30px;
right: 30px;
}
}
.addressList {
ul {
li {
padding: 20px 30px;
.items {
@include sc(28px, $fc);
@include fcb;
.checkIcon {
@include wh(28px, 20px);
@include fcc;
display: none;
img {
@include wh(100%, 100%);
}
}
.showIcon {
display: block;
}
}
}
}
}
}
}
后端返回数据效果图
根据用户选择: 保存当前操作的
id(parent_id参数)
,调用接口返回相关数据
-
type
就是currentType
的值【默认是1】: 1—>省,2—>市,3—>区,4—>街道
数据库结构效果图
仅供参考:根据需求定义
- 例:选择北京市北京市辖区东城区东华门街道
当选择北京对应id
为2
,根据id
查询对应市
。选择市对应id
为3
,根据id
查询区
,以此类推。