vue3+vant3封装省市区组件
因为后台返回的数据格式和vant不一致,所以自己遍历循环得到自己想到的格式。
省市区的接口并不是一个以children格式,一次性全部获取,而是选择市的时候需要得到省的id,一层一层请求接口才能得到省市区。
父组件:
1 <selectArea 2 @addressOnFinish="onChangeArea" 3 :addressObject="addressObject" 4 /> 5 6 import selectArea from "./../components/selectArea"; 7 export default { 8 components: { 9 selectArea, 10 }, 11 const addressObject = ref({}); //定义子组件对象 12 // 切换区域 13 const onChangeArea = (val) => { 14 console.log(val)//得到省市区,和name 15 };16 17 return { 18 onChangeArea, 19 addressObject, 20 };
子组件代码:
1 <template> 2 <van-nav-bar 3 :title="addressObject.address" 4 class="headerTop" 5 @click-left="onClickBack" 6 > 7 <template #right> 8 <img 9 src="../../static/assets/change.png" 10 alt="" 11 width="20" 12 @click="addressShow = true" 13 /> 14 </template> 15 </van-nav-bar> 16 17 <van-popup v-model:show="addressShow" round position="bottom"> 18 <van-cascader 19 v-model="addressObject.region" 20 title="请选择地区" 21 :options="addressList" 22 @change="onChange" 23 @close="addressShow = false" 24 @finish="addressOnFinish" 25 /> 26 </van-popup> 27 </template> 28 29 <script setup> 30 import { ref, toRefs, defineProps, defineEmits } from "vue"; 31 import { queryArea } from "./../../api/commonApi"; 32 import { closeToast, showLoadingToast } from "vant"; 33 import { useRouter } from "vue-router"; 34 const props = defineProps({ 35 addressObject: Object, 36 }); 37 const { addressObject } = toRefs(props); 38 39 const addressFieldValue = ref(""); //湖南省/长沙市/芙蓉区 40 var addressList = ref(""); 41 const addressShow = ref(false); 42 const addressValue = ref(""); //288 43 const province = ref(""); 44 const city = ref(""); 45 const region = ref(""); 46 const type = ref("1"); 47 const parentId = ref(""); 48 console.log("addressObject", addressObject.value); 49 const emit = defineEmits(["addressOnFinish"]); 50 const router = useRouter(); 51 setTimeout(() => { 52 // 判断是否有省id 没有是初始化 有是已新增数据并赋值 53 if (addressObject.value.region) { 54 var obj = { 55 type: 2, 56 parentId: addressObject.value.province, 57 }; 58 // 根据省id查询市并赋值到children 59 queryArea(obj) 60 .then((res) => { 61 if (res.data.code === 200) { 62 // console.log("省循环父id",addressList) 63 var res = res.data.data; 64 var options = []; 65 var obj = {}; 66 // 循环出vant想要的格式 67 console.log("addressList.value", addressList.value); 68 console.log("市res", res); 69 for (let i = 0; i < res.length; i++) { 70 obj = { 71 text: res[i].name, 72 value: res[i].id, 73 id: res[i].id, 74 type: res[i].type, 75 children: [], //省里面带children才能出现市区 市区里面带children可出现市区内区划 也就是省市区三级 所以是要把数据拼成这个格式即可 76 }; 77 options.push(obj); 78 } 79 for (let j = 0; j < addressList.value.length; j++) { 80 if (addressList.value[j].id == addressObject.value.province) { 81 addressList.value[j].children = options; 82 for (let i = 0; i < options.length; i++) { 83 if (options[i].id == addressObject.value.city) { 84 // 根据市id查询区并赋值到children 85 var params = { 86 type: 3, 87 parentId: addressObject.value.city, 88 }; 89 queryArea(params) 90 .then((res) => { 91 if (res.data.code === 200) { 92 // console.log("区循环父id",addressList) 93 var res = res.data.data; 94 var list = []; 95 var item = {}; 96 // 循环出vant想要的格式 97 for (let i = 0; i < res.length; i++) { 98 item = { 99 text: res[i].name, 100 value: res[i].id, 101 id: res[i].id, 102 type: res[i].type, 103 }; 104 list.push(item); 105 // console.log("市加children为区并且赋值list",list) 106 for ( 107 let n = 0; 108 n < addressList.value[j].children.length; 109 n++ 110 ) { 111 if ( 112 addressList.value[j].children[n].id == 113 addressObject.value.city 114 ) { 115 addressList.value[j].children[n].children = list; 116 // 根据市id查询区并赋值到children 117 } 118 } 119 } 120 // console.log("省加children并且赋值",addressList) 121 } 122 }) 123 .catch((error) => { 124 showToast(error); 125 }); 126 return; 127 } 128 } 129 } 130 } 131 // console.log("省加children并且赋值",addressList) 132 } 133 }) 134 .catch((error) => {}); 135 } 136 }, 1000); 137 138 const onClickBack = () => router.push("/home"); 139 const queryAreaData = async () => { 140 var obj = { 141 type: type.value, 142 parentId: parentId.value, 143 }; 144 queryArea(obj) 145 .then((res) => { 146 if (res.data.code === 200) { 147 var res = res.data.data; 148 var options = []; 149 var obj = {}; 150 for (var i = 0; i < res.length; i++) { 151 obj = { 152 text: res[i].name, 153 value: res[i].id, 154 id: res[i].id, 155 type: res[i].type, 156 children: [], //省里面带children才能出现市区 市区里面带children可出现市区内区划 也就是省市区三级 所以是要把数据拼成这个格式即可 157 }; 158 options.push(obj); 159 } 160 addressList.value = options; 161 } 162 }) 163 .catch((error) => {}); 164 }; 165 const onChange = ({ selectedOptions, value, tabIndex }) => { 166 if (tabIndex != 2) { 167 showLoadingToast("加载中..."); 168 setTimeout(() => { 169 var obj = { 170 type: tabIndex + 2, 171 parentId: value, 172 }; 173 queryArea(obj) 174 .then((res) => { 175 if (res.data.code === 200) { 176 closeToast(); 177 var res = res.data.data; 178 var options = []; 179 var obj = {}; 180 for (var i = 0; i < res.length; i++) { 181 // 判断是第几层 不需要 children 182 if (res[i].type <= 2) { 183 obj = { 184 text: res[i].name, 185 id: res[i].id, 186 parentId: res[i].parentId, 187 value: res[i].id, 188 type: res[i].type, 189 children: [], //省里面带children才能出现市区 市区里面带children可出现市区内区划 也就是省市区三级 所以是要把数据拼成这个格式即可 190 }; 191 } else { 192 obj = { 193 text: res[i].name, 194 id: res[i].id, 195 parentId: res[i].parentId, 196 value: res[i].id, 197 type: res[i].type, 198 }; 199 } 200 options.push(obj); 201 } 202 203 selectedOptions[tabIndex].children = options; 204 selectedOptions[tabIndex].children = res.data.data 205 .map((option) => option.name) 206 .join("/"); 207 } 208 }) 209 .catch((error) => {}); 210 }, 1000); 211 } 212 }; 213 // 全部选项选择完毕后,会触发 finish 事件 214 const addressOnFinish = ({ selectedOptions }) => { 215 addressShow.value = false; 216 addressObject.value.address = selectedOptions 217 .map((option) => option.text) 218 .join("/"); 219 for (let i = 0; i < selectedOptions.length; i++) { 220 region.value = selectedOptions[2].id; 221 } 222 // emit("addressOnFinish", region.value); 223 var params = { 224 province: selectedOptions[0].id, 225 city: selectedOptions[1].id, 226 region: region.value, 227 address: addressObject.value.address, 228 }; 229 emit("addressOnFinish", params); 230 }; 231 232 queryAreaData(); 233 </script> 234