springboot+vue省市县街道地区四级联动
1. 级联选择器实现省市县街道四级联动
2. 下拉框实现省市县街道四级联动
1. 级联选择器实现省市县街道四级联动
首先我们可以看到[Element ui](组件 | Element) 官网里的级联选择器的数据其实是树形的,所以我们可以在后端就把数据构造成树形结构的。有需要的小伙伴可以看我的另一篇博客:java–list转树形结构,这里就不再多讲。
1. 如果后台传过来的数据是树形结构的,那么我们直接绑定数据就可以了:
后台传过来的数据:
<template>
<div>
<el-row>
<el-cascader
v-model="value"
:props="props"
:options="result"
style="width: 50%"
></el-cascader>
</el-row>
</div>
</template>
<script>
import { getAddress } from "@/utils/api";
export default {
name: "Home",
data() {
return {
//这里需要改成和后端传过来的属性名一致,不然渲染不上,因为默认的是label,value,当然也可以把后端传过来的属性名改变为label和value
props: {
label: "name",
value: "name",
children: "children",
},
value: "",
result: [],
};
},
created() {
this.getAllAddress();
},
methods: {
getAllAddress() {
getAddress().then((res) => {
this.result = res.data.data;
});
},
},
};
</script>
效果:
2.如果后台传过来的不是树形结构,那我们就要在前端把它构造成树形结构。
后台传过来的数据:
前端代码(主要代码是使用递归将扁平数据构造为树形数据):
<template>
<div>
<el-row>
<el-cascader
v-model="value"
:props="props"
:options="result"
style="width: 50%"
></el-cascader>
</el-row>
</div>
</template>
<script>
import { getAddress } from "@/utils/api";
export default {
name: "Home",
data() {
return {
props: {
label: "name",
value: "name",
children: "children",
},
value: "",
result: [],
};
},
created() {
this.getAllAddress();
},
methods: {
getAllAddress() {
getAddress().then((res) => {
var list = [];
let addressData = res.data.data;
// 调用递归方法 传入的值(源数据,根节点的pid,一个空数组)
this.result = this.getTree(addressData, "0", list);
});
},
getTree(rootList, id, list) {
// 遍历源数组
for (var i = 0; i < rootList.length; i++) {
// 如果数组里每一个对象的pid==0
if (rootList[i].pid == id) {
// 就把当前对象push到list中,list中装的数据就是pid==0的对象,也就是根节点
list.push(rootList[i]);
}
}
// 遍历根节点list
for (var j = 0; j < list.length; j++) {
// 给list设置一个children属性
list[j].children = [];
// 再次调用递归 传入的值(源数据,根节点的id,一个空数组(也就是根节点的children))
// 这样就会无线循环完所有的数据
this.getTree(rootList, list[j].id, list[j].children);
// 这里需要判断根节点的children是否有值
if (list[j].children.length == 0) {
// 如果没有把它删除
delete list[j].children;
}
}
return list;
},
},
};
</script>
效果:
至于为什么要判断根节点的children是否有值。如果不判断,就会出现children是一个空数组,对比下面两张图就知道了。
判断后:
没有判断:
2. 下拉框实现省市县街道四级联动
如果后端返回的数据也是扁平数据,那么我们可以先筛选出省份数据(pid==0),在改变省份数据的时候,又筛选出市级数据,也就是市级的pid等于省级的id,以此内推即可;代码如下:
<template>
<div>
<el-row>
<el-select v-model="privince" @change="changeProvince">
<el-option
v-for="item in privinceData"
:key="item.id"
:value="`${item.id}|${item.name}`"
:label="item.name"
>
</el-option>
</el-select>
<el-select v-model="city" @change="changeCity">
<el-option
v-for="item in cityData"
:key="item.id"
:value="`${item.id}|${item.name}`"
:label="item.name"
>
</el-option>
</el-select>
<el-select v-model="area" @change="changeArea">
<el-option
v-for="item in areaData"
:key="item.id"
:value="`${item.id}|${item.name}`"
:label="item.name"
>
</el-option>
</el-select>
<el-select v-model="stree">
<el-option
v-for="item in streeData"
:key="item.id"
:value="item.name"
:label="item.name"
>
</el-option>
</el-select>
<el-button @click="save" type="primary">提交</el-button>
</el-row>
</div>
</template>
<script>
import { getAddress } from "@/utils/api";
export default {
name: "Home",
data() {
return {
privince: "",
city: "",
area: "",
stree: "",
privinceData: [],
cityData: [],
areaData: [],
streeData: [],
address: [],
};
},
created() {
this.getProvince();
},
methods: {
getProvince() {
// 获取数据
getAddress().then((res) => {
this.address = res.data.data;
// 筛选出身份数据
this.privinceData = this.address.filter((itme) => itme.pid == "0");
});
},
changeProvince(value) {
// 当省份数据改变时,根据id查找出当前省份下的城市
// 为什么会用`${item.id}|${item.name}`,因为我们只能根据省份的id找到它下面的城市,但是我们存入数据库的又是它的名字(例如江苏省),所以我用了`${}`来拼接变量
var id = value.split("|")[0];
// 上面代码的意思(举例):
// 此时的 value = 0|江苏省,根据 | 分割为一个数组,数组里第一个元素为0,第二个元素为江苏省,再取第一个元素
// 此时的id==0
this.cityData = this.address.filter((item) => item.pid == id);
this.city = "";
this.area = "";
this.stree = "";
},
changeCity(value) {
var id = value.split("|")[0];
this.areaData = this.address.filter((item) => item.pid == id);
this.area = "";
this.stree = "";
},
changeArea(value) {
var id = value.split("|")[0];
this.streeData = this.address.filter((item) => item.pid == id);
this.stree = "";
},
},
};
</script>
效果:
解释得可能不是那么清楚,大家多多包涵!