由elemnent-ui模拟一个全选、反选效果想到的购物车逻辑案例

最近做一个小例子,主要是要实现一个类似淘宝购物车那种效果。主要的功能点有如下几点:

1最顶层的复选框,实现全选、全不选

2每个商家店铺前有一个复选框,实现全选(该店铺下的商品)全选、全不选

3 每个商家店铺里的商品在勾选的时候,逐一勾选直到全部勾选,当前商家店铺前的复选框会勾选,当此操作依次进行,所有商家店铺前的复选框都勾选时,最顶层的复选框实现全选,反之状态变更为-

再测试这个例子之前,官方的demo过于简单,所以对element-ui的checkbox、<el-checkbox-group>做了一些梳理:

(1)el-checkbox-group绑定的是数组,记录了当前组里当前勾选的集合。也就是el-checkbox-group的v-model的值实际就是当前组里当前勾选的集合

(2)el-checkbox-group 里v-model的值和 组里el-checkbox的关系如下:

<el-checkbox-group
   v-model="item.checkedCities"
   @change="(val)=>handleCheckedCitiesChange(val,item)"
>
     <el-checkbox 
         v-for="(k,index) in item.list" 
        :key="index" 
        :label="k" >
            {{k.city}}
     </el-checkbox>
</el-checkbox-group>

这里:label="k"绑定的值的理解至关重要,如果label="k.id",那么el-checkbox-group里checkedCities就是所有组内元素id的集合,如果label="k.name",那么el-checkbox-group里checkedCities就是所有组内元素name的集合,如果label="k",那么el-checkbox-group里checkedCities就是所有组内元素的集合.
官方的说明文档中el-checkbox 的v-model的可选是是简单数据类型(number,string,boolean),实测绑定一个{}比如本例中的k也是可以的

(3)对于checkbox本身有两个属性要注意:

        checked------------>true:勾选,  fasle:不勾选

        indeterminate----->true:横线:  false :什么都没有

 

 理解这两个状态非常重要。这里还有一点要注意的是:checkbox的checked属性为true的时候,必须让其indeterminate的状态为false。因为checkbox只能有一个样式控制。要么是-横线,要么是√。

接下来我们看看数据结构:

const lists=[
    {
        name:"华中",
        checkGroupStatus:false,
        isIndeterminate:false,   
        checkedCities:[],
        list:[                    
            {
                checked:false,
                city:"shanghai",
            },
            {
                checked:false,
                city:"tianjing",
            },
            {
                checked:false,
                city:"wuhan",
            },
            {
                checked:false,
                city:"shenyang",
            },
            {
                checked:false,
                city:"changsha",
            }
        ]
    },
    {   
        name:"华东",
        checkGroupStatus:false,
        isIndeterminate:false, 
        checkedCities:[],
        list:[                    
            {
                checked:false,
                city:"langzhou",
            },
            {
                checked:false,
                city:"jingzho",
            },
            {
                checked:false,
                city:"hanzhong",
            },
            {
                checked:false,
                city:"wuxi",
            },
            {
                checked:false,
                city:"suzhou",
            }
        ]
    }, 
    {
        name:"华北",
         checkGroupStatus:false,
        isIndeterminate:false,
        checkedCities:[],
        list:[
                {
                    checked:false,
                    city:"guangzhou",
                },
                {
                    checked:false,
                    city:"shenzhen",
                },
                {
                    checked:false,
                    city:"nanchang",
                },
                {
                    checked:false,
                    city:"chengdu",
                },
                {
                    checked:false,
                    city:"xian",
                }
        ]
    },
    {
        name:"华南",
         checkGroupStatus:false,
        isIndeterminate:false,
        checkedCities:[],
        list:[
                {
                    checked:false,
                    city:"qingdao",
                },
                {
                    checked:false,
                    city:"xuzhou",
                },
                {
                    checked:false,
                    city:"yangzou",
                },
                {
                    checked:false,
                    city:"beijing",
                },
                {
                    checked:false,
                    city:"lasa",
                }
        ]
    }
]

 再看看html结构:

<div>
            <el-checkbox
                v-model="checkAll"
                :indeterminate="indeterminateAll"
                @change="handleCheckAllChange"
            >
            全选
            </el-checkbox>
        </div>
        <div class="group" v-for="item in testArr" :key="item.name">
            <el-checkbox
                v-model="item.checkGroupStatus"
                :indeterminate="item.isIndeterminate"
                @change="(val)=>handleCheckGroup(val,item)"
            >
              {{item.name}}
            </el-checkbox>
            <div >
                <el-checkbox-group
                    v-model="item.checkedCities"
                    @change="(val)=>handleCheckedCitiesChange(val,item)"
                >
                    <el-checkbox  v-for="(k,index) in item.list" :key="index" :label="k" >{{k.city}}</el-checkbox>
                </el-checkbox-group>
            </div>
        </div>
</div>

最后看看具体逻辑:

const handleCheckAllChange = () => {
   
    if(checkAll.value){
        testArr.forEach(group=>{
            group.checkedCities=group.list;
            group.checkGroupStatus=true
            group.list.forEach(k=>k.checked=true)
        })
    }else{
         testArr.forEach(group=>{
            group.checkedCities=[];
            group.checkGroupStatus=false
            group.list.forEach(k=>k.checked=false)
        })
    }
}
//勾选group的复选项选择当前组
const handleCheckGroup=(val,group)=>{
    if(val){
         group.list.forEach(ele => {
            group.checkedCities.push(ele)    
        })
    }else{
        if(!val){
            group.checkedCities=[]
            group.list.forEach(k=>k.checked=false)
        }
    }   
      //影响整体
    checkAllStatus()
    item.isIndeterminate= false;
}
const handleCheckedCitiesChange = (value,item) => {

    item.checkGroupStatus = item.checkedCities.length === item.list.length?true:false;
    item.isIndeterminate = item.checkedCities.length > 0 && item.checkedCities.length < item.list.length
  //影响整体全选
    checkAllStatus()
}

const checkAllStatus=()=>{
    let isAll= testArr.every(group=>group.checkedCities.length==group.list.length)?true:false;
    if(isAll){
        checkAll.value=true
        indeterminateAll.value=false
    }else{
        checkAll.value=false
         indeterminateAll.value=true
    }
}

     以下是整体代码:

<template>
    <div>
        <div>
            <el-checkbox
                v-model="checkAll"
                :indeterminate="indeterminateAll"
                @change="handleCheckAllChange"
            >
            全选
            </el-checkbox>
        </div>
        <div class="group" v-for="item in testArr" :key="item.name">
            <el-checkbox
                v-model="item.checkGroupStatus"
                :indeterminate="item.isIndeterminate"
                @change="(val)=>handleCheckGroup(val,item)"
            >
              {{item.name}}
            </el-checkbox>
            <div >
                <el-checkbox-group
                    v-model="item.checkedCities"
                    @change="(val)=>handleCheckedCitiesChange(val,item)"
                >
                    <el-checkbox  v-for="(k,index) in item.list" :key="index" :label="k" >{{k.city}}</el-checkbox>
                </el-checkbox-group>
            </div>
        </div>
    </div>

</template>

<script  setup>

import { reactive, ref } from 'vue'
//全选状态控制
const checkAll=ref(false);
const indeterminateAll=ref(false);


const lists=[
    {
        name:"华中",
        checkGroupStatus:false,
        isIndeterminate:false,   
        checkedCities:[],
        list:[                    
            {
                checked:false,
                city:"shanghai",
            },
            {
                checked:false,
                city:"tianjing",
            },
            {
                checked:false,
                city:"wuhan",
            },
            {
                checked:false,
                city:"shenyang",
            },
            {
                checked:false,
                city:"changsha",
            }
        ]
    },
    {   
        name:"华东",
        checkGroupStatus:false,
        isIndeterminate:false, 
        checkedCities:[],
        list:[                    
            {
                checked:false,
                city:"langzhou",
            },
            {
                checked:false,
                city:"jingzho",
            },
            {
                checked:false,
                city:"hanzhong",
            },
            {
                checked:false,
                city:"wuxi",
            },
            {
                checked:false,
                city:"suzhou",
            }
        ]
    }, 
    {
        name:"华北",
         checkGroupStatus:false,
        isIndeterminate:false,
        checkedCities:[],
        list:[
                {
                    checked:false,
                    city:"guangzhou",
                },
                {
                    checked:false,
                    city:"shenzhen",
                },
                {
                    checked:false,
                    city:"nanchang",
                },
                {
                    checked:false,
                    city:"chengdu",
                },
                {
                    checked:false,
                    city:"xian",
                }
        ]
    },
    {
        name:"华南",
         checkGroupStatus:false,
        isIndeterminate:false,
        checkedCities:[],
        list:[
                {
                    checked:false,
                    city:"qingdao",
                },
                {
                    checked:false,
                    city:"xuzhou",
                },
                {
                    checked:false,
                    city:"yangzou",
                },
                {
                    checked:false,
                    city:"beijing",
                },
                {
                    checked:false,
                    city:"lasa",
                }
        ]
    }
]
const testArr=reactive(lists)

const handleCheckAllChange = () => {
   
    if(checkAll.value){
        testArr.forEach(group=>{
            group.checkedCities=group.list;
            group.checkGroupStatus=true
            group.list.forEach(k=>k.checked=true)
        })
    }else{
         testArr.forEach(group=>{
            group.checkedCities=[];
            group.checkGroupStatus=false
            group.list.forEach(k=>k.checked=false)
        })
    }
}
//勾选group的复选项选择当前组
const handleCheckGroup=(val,group)=>{
    if(val){
         group.list.forEach(ele => {
            group.checkedCities.push(ele)    
        })
    }else{
        if(!val){
            group.checkedCities=[]
            group.list.forEach(k=>k.checked=false)
        }
    }   
      //影响整体
    checkAllStatus()
    group.isIndeterminate= false;
}
const handleCheckedCitiesChange = (value,item) => {

    item.checkGroupStatus = item.checkedCities.length === item.list.length?true:false;
    item.isIndeterminate = item.checkedCities.length > 0 && item.checkedCities.length < item.list.length
  //影响整体全选
    checkAllStatus()
}

const checkAllStatus=()=>{
    let isAll= testArr.every(group=>group.checkedCities.length==group.list.length)?true:false;
    if(isAll){
        checkAll.value=true
        indeterminateAll.value=false
    }else{
        checkAll.value=false
         indeterminateAll.value=true
    }
}

</script>

<style  scoped>

</style>

 提一点的是:真实的项目中对于每一个商品,勾选它呈现的状态后端是不可能给我们这个状态值的。对于每个店铺,勾选它时它的状态。也就是我们例子中的checkGroupStatus和isIndeterminate后端也不可能给我们。所以需要我在获取原始数据以后改造数据,添加这几个字段来记录其状态。这个也很简单。forEach循环给item,$set(item,"checkex",false),$set(group,"checkGroupStatus",false)即可。其他同理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值