Vue3实现地址多选

起因

vue3实现一个区域多选的选择框
用户需求是可以选择服务区域,本来想找个省市县级联的一个选择框就好了,但是又要求多选,而且是用户自己给出区域,无奈写一个,特记录下,顺便帮助后来者

实现效果

效果演示

实现思路

  1. 使用一个div将添加区域给放起来,display设置为none,当点击添加时将这个div的display设置为block,实现添加区域的隐藏和显示
  2. 下拉框值改变时去改变选中索引(provinceIndex)这个变量,实现citybox中显示的城市内容的改变
  3. 点击城市内容时触发选中/取消选中 方法,其实为同一个方法,通过判断当前点击元素的class(class中包含is-selected则是已经选中的)来分辨是选中还是取消选中
  4. 在选中方法里将选中的对象添加到一个存放选中内容的列表(citys)中,并给点击元素的class添加上is-selected类,如果是取消选中则会在在citys列表做一个筛选,将取消的内容给去除
  5. 清空方法则是将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>
    

总结

以上

内容已经说得比较详细了,特此记录


如对你有所帮助的话可以帮我点个赞,感谢

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

li-xun

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值