我们可能会有用到多选城市的情况、那么我们详解一下怎么实现多选城市并展示
一、效果图
1-1默认展示
1-2展开效果
1-3选中效果
1-4确认选择展示
二、代码-父组件(详解)
2-1父组件templete部分
<div @click="chooseCity" style="margin-top:100px">点击选择城市</div>
<div class="contentTags">
<city-tags v-if="chooseshowCity" :option="selectCityInfo" @cancelCity="cancelCity" @saveCity="saveCity"></city-tags>
</div>
<div v-if="paramsData.citys>0">展示城市</div>
<div style="margin-bottom:100px"> <span style="border:1px solid #3370FF;margin:4px;padding: 0 4px;display: inline-block;" v-for="(cityItem,cityIndex) in paramsData.citys" :key="cityIndex+'cityIndex'"> {{cityItem.parentName}}-{{cityItem.name}}</span></div>
2-2 在父组件中写一个组件引入
import cityTags from "./components/cityTags.vue";
components:{
cityTags
},
2-3 js-data
paramsData:{citys:[{code:'120100',name:'天津市',parentCode:'120000',parentName:'天津'}]},
selectCityInfo:{
name:'城市选择',title:'城市选择(多选)',arr:[],type:'checkbox',ids:[],
chooseItem:[]
}
paramsData :为模拟展示:比如我们从详情接口获取的数据存在默认展示在页面中。
selectCityInfo:为传入子组件的数据。arr为全部的城市、ids为唯一标识的数组(例如code、id等)、chooseItem为选中的数据,默认为citys中的格式
2-4 js中方法
mounted() {
this.getCityList();
},
methods:{
//初始化数据
initCitys(){
let cityIds = [];
let cityItem = [];
this.paramsData.citys.forEach((ele)=>{
cityIds.push(ele.code);
cityItem.push(ele);
});
this.selectCityInfo.ids = JSON.parse(JSON.stringify(cityIds));
this.selectCityInfo.chooseItem = JSON.parse(JSON.stringify(cityItem));
},
//子组件传回的确定事件
saveCity(ids,chooseItem){
this.paramsData.citys=JSON.parse(JSON.stringify(chooseItem))
this.chooseshowCity=false
},
//子组件传回的取消展示选择框事件
cancelCity(){
this.chooseshowCity=false
},
//展示选择框事件
chooseCity(){
this.initCitys()
this.chooseshowCity=true
},
//获取城市接口(根据各自的接口获取即可)
getCityList(){
cityList(100000).then((res)=>{
res.data.child.forEach((element)=>{
element.child.forEach((ele)=>{
ele.parentName=element.name //为child数据加上了父级的名字
})
})
this.selectCityInfo.arr= res.data.child
this.initCitys()
})
},
}
2-5父组件css
.userInfo_warp .contentTags{
position: fixed;left: 3%;width: 94%;background-color: #fff;top:200px;box-shadow: 0px 1px 8px 0px rgba(0, 0, 0, 0.2);z-index: 999;
}
?3、代码-子组件(详解)
3-1 子组件templete
<template>
<div class="tags_warp">
<div class="count">
//循环展示外层数据(例如北京、天津、河北)
<div class="tagsKey">
<div class="item" v-for="(cityItem,cityIndex) in option.arr" :key="cityIndex+'cityIndex'" :class="[cityIndex==chooseKey?'chooseItem':'']" @click="clickItem(cityIndex)">{{cityItem.name}}
<span class="itemNum" v-if="cityItem.num>0">{{cityItem.num}}</span>
</div>
</div>
<div class="tagsKey">
//循环展示里层数据 (北京市、天津市、承德市等)
<div :class="['item',option.arr[chooseKey].child.length==option.arr[chooseKey].num?'chooseItem':'']" @click="chooseAll(chooseKey)">全选</div>
<div v-for="(citychildItem,citychildIndex) in option.arr[chooseKey].child" :key="citychildIndex+'citychildIndex'" :class="['item',option.ids.includes(citychildItem.code)?'chooseItem':'']" @click="chooseBox(citychildItem,chooseKey)">{{citychildItem.name}}</div>
</div>
</div>
<div class="bot">
<div @click="saveCity('重置')">重置</div>
<div @click="cancelCity">取消</div>
<div @click="saveCity('确定')">确定</div>
</div>
</div>
</template>
3-2js部分
<script>
export default {
components: {},
props: {
//接收父组件传递的数据
option:{
type:Object,
default:()=>{
return {name:'城市选择',title:'城市选择(多选)',arr:[],ids: [],type:'checkbox',chooseItem:[]}
}
}
},
data() {
return {
chooseKey:0//默认展示为最顶层数据(点击时切换chooseKey)
};
},
watch: {},
computed: {},
methods: {
//保存
saveCity(type){
if(type=='重置'){
this.option.chooseItem=[],
this.option.ids=[]
this.initCity()
}
else{
//点击确定时传回数据
this.$emit('saveCity',this.option.ids,this.option.chooseItem)
}
},
//取消事件
cancelCity(){
this.$emit('cancelCity')
},
//选中取消选中事件
chooseBox(item,index){
//code唯一标识存在找到对应下标删除
if(this.option.ids.includes(item.code)){
let findIndex=this.option.ids.findIndex((ele)=>{
return ele==item.code
})
this.option.ids.splice(findIndex,1)
this.option.chooseItem.splice(findIndex,1)
}else{
//code不存在则添加
this.option.ids.push(item.code)
this.option.chooseItem.push(item)
}
this.initCity()
},
//全选取消全选事件
chooseAll(index){
let arrid=[]
let arrItem=[]
//取消全选
if(this.option.arr[index].child.length==this.option.arr[index].num){
this.option.ids.forEach((element)=>{
let flag=true
//如果选中下标下二级城市有对应的则不往数组中添加
this.option.arr[index].child.forEach((ele)=>{
if(element==ele.code){
flag=false
}
})
if(flag){
arrid.push(element)
}
})
this.option.chooseItem.forEach((element)=>{
let flag=true
//如果选中下标下二级城市有对应的则不往数组中添加
this.option.arr[index].child.forEach((ele)=>{
if(element.code==ele.code){
flag=false
}
})
if(flag){
arrItem.push(element)
}
this.option.ids=arrid
this.option.chooseItem=arrItem
})
}else{
//code不存在时添加
this.option.arr[index].child.forEach((ele)=>{
if(!this.option.ids.includes(ele.code)){
this.option.ids.push(ele.code)
this.option.chooseItem.push(ele)
}
})
}
this.initCity()
},
//初始化展示num 每个二级标签中选中了几个 num>0时展示
initCity(){
this.option.arr.forEach(element => {
let num=0
element.child.forEach((ele)=>{
if(this.option.ids.includes(ele.code)){
num++
}
})
element.num=num
});
},
//点击一级城市时取下标 展示二级城市
clickItem(index){
this.chooseKey=index
}
},
created() {
this.initCity()
},
mounted() {
}
};
?3-3css部分
<style scoped>
.tags_warp{padding-bottom: 10px;border-top: 1px solid #F3F4F4;min-height: 100px;}
.tags_warp .count{display: flex;}
.tags_warp .count .tagsKey{flex: 1;max-height: 180px;overflow-y: auto;}
.tags_warp .chooseItem{background-color: lightblue;opacity: .7;}
.tags_warp .item{padding:4px;margin:1px 0px; position: relative;}
.tags_warp .item .itemNum{position: absolute;right:10px;font-size: 10px;color: #3370FF;}
.tags_warp .bot{display: flex;}
.tags_warp .bot div{flex:1;text-align: center;}
</style>
|