起因
vue3实现一个区域多选的选择框
用户需求是可以选择服务区域,本来想找个省市县级联的一个选择框就好了,但是又要求多选,而且是用户自己给出区域,无奈写一个,特记录下,顺便帮助后来者
实现效果
实现思路
- 使用一个div将添加区域给放起来,display设置为none,当点击添加时将这个div的display设置为block,实现添加区域的隐藏和显示
- 下拉框值改变时去改变选中索引(provinceIndex)这个变量,实现citybox中显示的城市内容的改变
- 点击城市内容时触发选中/取消选中 方法,其实为同一个方法,通过判断当前点击元素的class(class中包含is-selected则是已经选中的)来分辨是选中还是取消选中
- 在选中方法里将选中的对象添加到一个存放选中内容的列表(citys)中,并给点击元素的class添加上is-selected类,如果是取消选中则会在在citys列表做一个筛选,将取消的内容给去除
- 清空方法则是将citys列表清空,并且将有is-selected类的class设置为正常
实现代码
- template部分
<template> <div class="form-item"> <label for="city" class="form-label">服务区域</label> <span> <span style="background-color: rgb(245,247,249);margin-right: 5px;" v-for="item in citys" :key="item">{{ item.name }}</span> <span @click="ClickAddCity" style="color: #0bbfbc;">点击添加</span> </span> <!-- 显示/隐藏部分 --> <div ref="citysDom" class="citysbox"> <div class="citysbox-top"> <div class="top-left"> <label for="city" class="form-label1">省份:</label> <select required id="city" name="city" class="form-input form-input-select" style="width: auto;color: #303030;" v-model="provinceIndex"> <option v-for="(item, index) in Provinces" :key="index" :value="index"> {{ item.name}} </option> </select> </div> <div class="top-right"> <button type="button" class="btn-close" @click="ClickAddCity">关闭</button> <button type="button" class="btn-confirm" @click="ClickReastBtn">清空</button> <button type="button" class="btn-confirm" @click="ClickAddCity">确认</button> </div> </div> <!-- 城市内容部分 --> <div class="citysbox-body"> <div v-for="item in Provinces[provinceIndex].city" :key="item.id" :class="citys.includes(item) ? 'box-item is-selected' : 'box-item'" @click="SelectChange(item, $event)"> {{ item.name }}</div> </div> </div> </div>
-
script部分
<script setup> import { ref } from 'vue'; // 省市信息 const Provinces = [ { "id": 24, "name": "北京市", "city": [ { "id": 268, "name": "东城区", "province": 24 }, { "id": 269, "name": "西城区", "province": 24 } ] }, { "id": 9, "name": "福建省", "city": [ { "id": 109, "name": "福州市", "province": 9 }, { "id": 110, "name": "厦门市", "province": 9 }, { "id": 116, "name": "龙岩市", "province": 9 } ] } ] // 添加服务区域相关 var citysDom = ref() // dom对象 var provinceIndex = ref(0) // 当前选择获取值 var citys = ref([]) // 已选择城市 // 点击添加时显示地址选择div function ClickAddCity() { if (citysDom.value.style.display !== 'block') citysDom.value.style.display = 'block'; else citysDom.value.style.display = 'none'; } // 选中地址 function SelectChange(item, e) { let domClass = e.currentTarget.getAttribute("class") // 判断item的class区别两种情况,一种是点击未选中的item选中 , 一种是点击已选中的取消选中 if (domClass == "box-item") { e.currentTarget.className = "box-item is-selected" // 将选中对象添加到citys列表中 citys.value.push(item) } else { e.currentTarget.className = "box-item" // 将取消选中对象从citys列表中去除 citys.value = citys.value.filter(val => val.id != item.id) } console.log('citys:', citys.value) } // 清空地址区域 function ClickReastBtn() { citys.value = [] let items = document.getElementsByClassName("is-selected"); console.log('length',items.length); console.log('items:',items, typeof(items)); // 清空已选择的样式 Array.prototype.forEach.call(items, function (item) { item.className = "box-item" }); } </script>
-
css部分
<style scoped> .form-item { margin-right: 24px; margin-bottom: 24px; } .form-label { height: 14px; font-size: 14px; color: #39475A; letter-spacing: 0; text-align: right; line-height: 14px; font-weight: 400; margin-right: 12px; } .citysbox { width: 700px; max-width: 750px; min-width: 360px; padding: 10px; min-height: 100px; display: none; position: absolute; background: rgb(245, 247, 249); border-radius: 10px; } .citysbox-top{ display: flex; flex-direction: row; justify-content: space-between; } .citysbox-body { display: flex; flex-direction: row; flex-wrap: wrap; } .box-item { margin: 10px 10px 0 0; border: rgb(197, 208, 223) solid 1px; border-radius: 4px; padding: 3px; } .is-selected { border: rgb(11, 192, 188) solid 1px; color: rgb(11, 192, 188); } </style>
总结
以上
内容已经说得比较详细了,特此记录
如对你有所帮助的话可以帮我点个赞,感谢