vue 实现多组合复选框案例

完成效果如图:

当我们点击标题全选时  指定店铺所有商品都被选中,取消时全取消

当我们选择某店铺商品数量等于该店铺所有商品时,该店铺全选按钮被选中

废话不多说,代码呈上  欢迎给出更好的方案实现该功能

----------------------------------------------------    goods_select.vue    ------------------------------------------------------------------

<template>
    <div class="goods-select-box big-box">
        <!--每个店铺的商品展示-->
        <div class="goods-shopp-box" v-if="mallData.length>0" v-for="Malls in mallData" >
            <div class="goods-shopp">            
                <span 
                    :class="hasSelectArr.indexOf(Malls.Mall.id)>=0?'checks':'removeCheck'"
                    @click="checkAll(Malls.Mall.id)"                
                    >                    
                </span>
                <i class="icons">赢</i>
                <span class="shopping-name hrefColor">{ {Malls.Mall.name}}</span>
            </div>
            <ul class="goods-detail-type">
                <li class="detail-item" v-for="items in Malls.Mall_detail">                        
                    <span 
                    :class="hasSelectArr.indexOf(items.id)>=0?'checks':'removeCheck'"
                    @click="checkOne(items.id,Malls.Mall.id)"                
                    >                    
                </span>
                    <div class="detail-item-text">
                        <div class="img-cont">
                            <img class="goods-img" :src="items.img">
                        </div>

                        <div class="intro-text">
                            <div class="intro-text-top">
                                <div class="text-top-left">
                                    <p class="title">{ {items.title}}</p>
                                    <p class="detail-goods-intro hrefColor">{ {items.num}}</p>
                                </div>
                                <div class="text-top-right">
                                    { {items.compare}}
                                </div>
                            </div>
                            <p class="intro-text-bottom">{ {items.rate}}</p>
                        </div>

                    </div>
                </li>
            </ul>
        </div>
        <div class="no-data" v-else>
            空空如也
        </div>
        <!--btn next step-->
        <button class="btn-next nav-and-btn">下一步</button>
    </div>
</template>

<script>
    import  Datas  from '../../../static/data.js'
    export default {
        data() {
            return {
                    // 定义一个盛放已选的容器
                    hasSelectArr:[],
                    //接收后台返回的数据
                    mallData:[]
            }
        },
        components: {

        },
        created(){
            this.mallData = [...Datas];
            
        },
        mounted() {
        },
            methods: {
            /*
             * @fun :全选方法
             * @params{id:商品识别id}
             */
            checkAll(id){
                let index = this.hasSelectArr.indexOf(id);
                if( index>= 0 && this.hasSelectArr.length){
                    //1.将该id splice  移除
                    this.hasSelectArr = this.hasSelectArr.filter(s=>{                    
                        return s!= id;
                    });
                    //2.取消所有商品
                    this._fremoveAllGoods( id );
                    
                }else{
                     
                     //1.将该id push到数组中            
                    this.hasSelectArr.push( id );
                     //2.将含有该id类似名的商品存放到数组中
                    this._fgetGoodsId( id )
                }            
            },
            /*
             * @fun :全选方法
             * @params{id:商品识别id}
             */
            _fgetGoodsId( id ){            
                 this.mallData.forEach(item=>{
                         if(id===item.Mall.id){
                             item.Mall_detail.forEach(val=>{
                                 
                                 if( this.hasSelectArr.indexOf(val.id)<0 ){
                                     this.hasSelectArr.push(val.id)
                                 }
                                 
                             })
                         }
                 })
            },
            
                /*
             * @fun :取消全选方法
             * @params{id:商品识别id}
             */
            _fremoveAllGoods( id ){                        
                var    len      = this.hasSelectArr.length,
                        indexs = '',
                        aimsId = '';
                //注意这里不能使用index和splice来做  因为hasSelectArr的元素一直在变化  所以这里用filter过滤更合适        
                
                this.hasSelectArr = this.hasSelectArr.filter(val=>{
                        indexs = val.indexOf('_');
                        //这里要分两种情况  当有下划线时
                        if( indexs >-1){
                                aimsId = val.substring(0,indexs);
                                return aimsId!=id;
                        //当没有下划线时 我们不需要进行截取  直接返回不等于就好        
                        }else if( indexs == -1 ){
                                return val!=id;
                        }
                })
                
                console.log(this.hasSelectArr)
            },
            /*
             * @fun :单选
             * @params{id:单个商品id,MallId:店铺的id}
             */
            checkOne( id,MallId ){
                var index         = this.hasSelectArr.indexOf( id ),
                        MallIndex = this.hasSelectArr.indexOf( MallId ),
                        num                = 0,
                        aims            = '';
                        
                //1.当该商品已被选择  则我们就将其取消 同时如果全选被勾选 则我们也取消全选        
                if( index>=0 ){
                        this.hasSelectArr = this.hasSelectArr.filter(val=>{
                             return val != id;
                        }).filter( vals=>{
                             return vals != MallId;
                        })                                        
                }else{
                //2.如果未被选择,则添加    
                    this.hasSelectArr.push( id );
                
                //3.假如所选商品的数量刚好等于后台传的数量则将全选勾上
                    if( MallIndex<0 ){
                        aims = id.substring(0,id.indexOf('_')+1)//获取同一个key来比对
                        this.hasSelectArr.map(item=>{
                            if( aims == item.substring(0,item.indexOf('_')+1) ){
                                num++;
                            }
                        });
                        if( num == this._fgetGoodsNum( MallId )){
                            this.hasSelectArr.push( MallId )
                        }
                    }                                            
                }                
            },
            /*
             * @fun :获取某店铺商品数
             * @params{id:店铺id}
             */
            _fgetGoodsNum( id ){
        
                var len;
                this.mallData.map(val=>{
                    if( id == val.Mall.id ){
                        len = val.Mall_detail.length;
                        
                    }
                })
                return len;
            }
            
        },
        
    }
</script>

<style scoped="scoped" lang="scss">
    $btnNext: 50px;
    @function px2rem($px) {
        $rem: 37.5px;
        @return ($px / $rem)+rem
    }
    
    /*选框 star*/
    .checks,.removeCheck{
        width: px2rem(20px);
        height: px2rem(20px);
        border-radius:50%;
        margin-right: px2rem(12px);
    }
    .checks{
        background-color: red;
    /*    background-image: url();*/
    }
    .removeCheck{
        background-color: yellow;
    /*    background-image: url();*/
    }
    /*选框 end*/
    
    .goods-select-box {
        min-height: 100%;
        padding-bottom: px2rem($btnNext);
    }
    
    .goods-shopp-box {
        background-color: white;
        margin-bottom: px2rem(10px);
        padding: 0 px2rem(10px) 0 px2rem(10px);
        border-bottom: 1px solid rgb(236, 236, 236);
    }
    
    .goods-shopp {
        padding: px2rem(10px) px2rem(5px);
        display: flex;
        align-items: center;
        border-bottom: 1px solid #ccc;
    }
    
    .inps {
        margin-right: px2rem(12px);
    }
    
    .icons {
        margin-right: px2rem(12px);
    }
    
    .goods-detail-type {
        li:last-child {
            border-bottom: none;
        }
    }
    
    .detail-item {
        display: flex;
        align-items: center;
        padding: px2rem(10px) 0 px2rem(10px) px2rem(5px);
        border-bottom: 1px dashed #ccc;
    }
    
    .detail-item-text {
        display: flex;
        flex: 1;
        max-height: 2.4rem;
    }
    
    .img-cont {
        width: px2rem(100px);
        /*height: 100%;*/
        margin-right: px2rem(12px);
        .goods-img {
            display: inline-block;
            width: 100%;
            height: 100%;
        }
    }
    
    .title {
        font-size: 14px;
    }
    
    .intro-text {
        flex: 1;
    }
    
    .intro-text-top {
        display: flex;
        justify-content: space-between;
        width: 100%;
    }
    
    .text-top-right {
        display: flex;
        align-items: center;
    }
    
    .intro-text-bottom {
        text-align: right;
    }
    /*下一步按钮*/
    
    .btn-next {
        position: fixed;
        bottom: 0;
        width: 100%;
        text-align: center;
        font-size: 15px;
        color: white;
        border: none;
        outline: none;
        background-color: #fb474a;
    }
</style>

--------------------------------------------------------------------模拟数据格式 -------------------------------------------------------------

import goodImg from "../src/assets/image/login/bgi.jpg"
const datas = [
    {
        Mall:{
            name:"缤纷果园-花园路店",
            id:"hk",
        },
        Mall_detail:[{
            id:'hk_1',
            img:goodImg,
            title:'[自营] 越南火龙果',
            num:'火龙果约500g/个',
            compare:'赠菜豆30个',
            rate:'x2'
        },{
            id:'hk_2',
            img:goodImg,
            title:'[自营] 越南火龙果',
            num:'火龙果约500g/个',
            compare:'赠菜豆30个',
            rate:'x2'
        },{
            id:'hk_3',
            img:goodImg,
            title:'[自营] 越南火龙果',
            num:'火龙果约500g/个',
            compare:'赠菜豆30个',
            rate:'x2'
        }]
    },
    {
        Mall:{
            name:"缤纷果园-槐树路店",
            id:"yy",
        },
        Mall_detail:[{
            id:'yy_1',
            img:goodImg,
            title:'[自营] 越南MV果',
            num:'MV果约50g/个',
            compare:'赠菜豆30个',
            rate:'x1'
        },{
            id:'yy_2',
            img:goodImg,
            title:'[自营] 越南MV果',
            num:'MV果约50g/个',
            compare:'赠菜豆30个',
            rate:'x1'
        },{
            id:'yy_3',
            img:goodImg,
            title:'[自营] 越南MV果',
            num:'MV果约50g/个',
            compare:'赠菜豆30个',
            rate:'x1'
        }]
    }
]

export default datas

猜你喜欢

转载自blog.csdn.net/weixin_41421227/article/details/88602703
今日推荐