IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> vue实现城市选择(多选)效果—手写组件(父子组件传值) -> 正文阅读

[JavaScript知识库]vue实现城市选择(多选)效果—手写组件(父子组件传值)

我们可能会有用到多选城市的情况、那么我们详解一下怎么实现多选城市并展示

一、效果图

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>

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-06-29 18:55:53  更:2022-06-29 18:59:47 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 12:46:44-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码