省市联动
本插件最后效果
属性指南
属性名 | 说明 | 类型 | 默认值 | 是否必须 |
---|---|---|---|---|
list | 省市联动地图数据格式类型必须有 code,name 具体看下图便知 | Array | 封装好了数据 | 非必须填写 |
provinceStyle | 省份样式 | cssObj | - | 非必须填写 |
cityStyle | 城市样式 | cssObj | - | 非必须填写 |
streetStyle | 区样式 | cssObj | - | 非必须填写 |
provinceplaceholder | 省份没输入的时候提示问题 | string | 请选择省份 | 非必须填写 |
cityplaceholder | 城市没输入的时候提示问题 | string | 请选择省份 | 非必须填写 |
streetplaceholder | 区域没输入的时候提示问题 | string | 请选择省份 | 非必须填写 |
provincedataprops | 传入省份数据反显的值 | {code: string , name: string } | - | 非必须填写 |
citydataprops | 传入城市数据反显的值 | {code: string , name: string } | - | 非必须填写 |
streetdataprops | 传入区数据反显的值 | {code: string , name: string } | - | 非必须填写 |
getResult | 获取最后的值方法 | 通过这个方法获取到最后省份城市 区域 | - | 必须填写 |
封装插件
类型
ts
export interface IData {
code: string;
name: string;
}
export interface IChooseAreaProps {
code: string;
name: string;
children?: IChooseAreaProps[];
}
export interface IChooseAreaState {
list?: IChooseAreaProps[];
provinceStyle?: Object;
cityStyle?: Object;
streetStyle?: Object;
provinceplaceholder?: string;
cityplaceholder?: string;
streetplaceholder?: string;
provincedataprops?: IData;
citydataprops?: IData;
streetdataprops?: IData;
}
组件
vue
<!--
* @Author: jsopy
* @Date: 2025-02-08 10:05:54
* @LastEditTime: 2025-02-09 21:14:06
* @FilePath: /demoall/src/components/chooseArea/src/index.vue
* @Description:
*
-->
<template>
<div>
<!--省份开始-->
<el-select
value-key="code"
v-model="provincedata"
:placeholder="props.provinceplaceholder"
:style="props.provinceStyle"
@change="getDataAll"
>
<el-option
v-for="item in worldoptions"
:label="item.name"
:value="item"
/>
</el-select>
<!--省份结束-->
<!--市区开始-->
<el-select
@change="getDataAll"
value-key="code"
v-model="citydata"
:placeholder="props.cityplaceholder"
:style="props.cityStyle"
>
<el-option
v-for="item in cityoptions"
:key="item.code"
:label="item.name"
:value="item"
/>
</el-select>
<!--市区结束-->
<!--街道开始-->
<el-select
value-key="code"
@change="getDataAll"
v-model="streetdata"
:placeholder="props.streetplaceholder"
:style="props.streetStyle"
>
<el-option
v-for="item in streetoptions"
:key="item.code"
:label="item.name"
:value="item"
/>
</el-select>
<!--街道结束-->
</div>
</template>
<script setup lang="ts">
import dataResult from "../lib/data.json";
import { ref, onMounted, watch, type CSSProperties } from "vue";
import { type IChooseAreaProps, type IData } from "@/types/chooseArea/type";
const emits = defineEmits<{
(e: "getResult", val: IData[]): void;
}>();
const props = withDefaults(
defineProps<{
list?: IChooseAreaProps[];
provinceStyle?: CSSProperties;
cityStyle?: CSSProperties;
streetStyle?: CSSProperties;
provinceplaceholder?: string;
cityplaceholder?: string;
streetplaceholder?: string;
provincedataprops?: IData;
citydataprops?: IData;
streetdataprops?: IData;
}>(),
{
list: () => {
return dataResult;
},
provinceStyle: () => {
return {};
},
cityStyle: () => {
return {};
},
streetStyle: () => {
return {};
},
provinceplaceholder: "请选择省份",
cityplaceholder: "请选择市区",
streetplaceholder: "请选择街道",
provincedataprops: () => {
return {
code: "",
name: "",
};
},
citydataprops: () => {
return {
code: "",
name: "",
};
},
streetdataprops: () => {
return {
code: "",
name: "",
};
},
}
);
// 省份
const provincedata = ref<IData>();
// 市区
const citydata = ref<IData>();
// street 街道
const streetdata = ref<IData>();
// 省市区list
const worldoptions = ref<IData[]>([]);
// 获取区list
const cityoptions = ref<IData[]>([]);
// 获取streetlist
const streetoptions = ref<IData[]>([]);
// 省份数据
// 获取市list
const getworldoptions = () => {
let result: IData[] = [];
props.list.forEach((item) => {
let obj = {
code: item.code,
name: item.name,
};
result.push(obj);
});
worldoptions.value = result;
};
// 获取市区
const getcityoptions = () => {
let result: IData[] = [];
props.list.forEach((item: IChooseAreaProps, index) => {
if (item.name === provincedata.value?.name) {
(item.children as IData[]).forEach((item) => {
let obj = {
code: item.code,
name: item.name,
};
result.push(obj);
});
}
});
cityoptions.value = result;
};
// 定义一个函数,用于获取街道选项
const getstreetoptions = () => {
// 定义一个空数组,用于存储街道选项
let result: IData[] = [];
// 遍历data数组
props.list.forEach((item: IChooseAreaProps, index: number) => {
// 如果当前项的name属性等于provincedata.value.name
if (item.name === provincedata.value?.name) {
// 遍历当前项的children数组
(item.children as IData[]).forEach(
(item: IChooseAreaProps, index: number) => {
// 如果当前项的name属性等于cityvalue.value
if (item.name === citydata.value?.name) {
// 遍历当前项的children数组
(item.children as IData[]).forEach(
(item: IChooseAreaProps, index: number) => {
// 定义一个对象,用于存储街道选项的code和name属性
let obj = {
code: item.code,
name: item.name,
};
// 将对象添加到result数组中
result.push(obj);
}
);
}
}
);
}
});
// 将result数组赋值给streetoptions.value
streetoptions.value = result;
};
// 监听省份变化
watch(
() => provincedata.value?.name,
(newval, oldval) => {
if (newval != oldval) {
if (oldval) {
citydata.value = { code: "", name: "" };
streetdata.value = { code: "", name: "" };
}
getcityoptions();
getstreetoptions();
}
},
{
deep: true,
immediate: true,
}
);
// 监听城市变化
watch(
() => citydata.value?.name,
(newval, oldval) => {
if (newval != oldval) {
if (oldval) {
streetdata.value = { code: "", name: "" };
}
getstreetoptions();
}
},
{
deep: true,
immediate: true,
}
);
// 封装一个方法获取所有的数据
const getDataAll = () => {
// emits.getResult([provincedata.value, citydata.value, streetdata.value])
setTimeout(() => {
emits("getResult", [
provincedata.value as IData,
citydata.value as IData,
streetdata.value as IData,
]);
}, 100);
};
onMounted(() => {
if (props.provincedataprops.name != "") {
provincedata.value = JSON.parse(JSON.stringify(props.provincedataprops));
}
if (props.citydataprops.name != "") {
console.log("ceshi");
citydata.value = JSON.parse(JSON.stringify(props.citydataprops));
}
if (props.streetdataprops.name != "") {
streetdata.value = JSON.parse(JSON.stringify(props.streetdataprops));
}
getworldoptions();
});
</script>
<style scoped></style>
调用组件
vue
<template>
<div class="pagecontent">
<yj-area
:provinceStyle="provinceStyle"
:cityStyle="cityStyle"
:streetStyle="streetStyle"
:provinceplaceholder="provinceplaceholder"
:cityplaceholder="cityplaceholder"
:streetplaceholder="streetplaceholder"
:provincedataprops="provincedataprops"
:citydataprops="citydataprops"
:streetdataprops="streetdataprops"
@getResult="getResultAll"
></yj-area>
<yj-area @getResult="getResultAll2"></yj-area>
</div>
</template>
<script setup lang="ts">
import { type IData } from "@/types/chooseArea/type";
import { ref } from "vue";
const provinceStyle = ref({
width: "300px",
marginRight: "10px",
});
const cityStyle = ref({
width: "200px",
marginRight: "20px",
});
const streetStyle = ref({
width: "300px",
marginRight: "30px",
});
const provinceplaceholder = ref("选择省份");
const cityplaceholder = ref("选择城市");
const streetplaceholder = ref("选择区县");
const provincedataprops = ref({ code: "12", name: "天津市" });
const citydataprops = ref({ code: "1201", name: "市辖区" });
const streetdataprops = ref({ code: "120103", name: "河西区" });
// 获取最后数据的方法
const getResultAll = (content: IData[]) => {
console.log(content);
};
// 获取最后数据的方法
const getResultAll2 = (content: IData[]) => {
console.log(content);
};
</script>
<style scoped lang="scss">
.pagecontent {
height: 100%;
}
</style>