指标:实现相似购物车的单选、多选、全选
实现如下:
<template> <div class="div-table"> <a-row type="flex" class="div-table-thead"> <a-col :span="aRowCol.img"> <a-checkbox v-model:checked="checkedAll" @change="onChangeCheckedAll"></a-checkbox> <span style="display: inline; margin-left: 20px">图片</span> </a-col> <a-col :span="aRowCol.name"> <span style="text-align: left">名称</span> </a-col> <a-col :span="aRowCol.price"> <span>价格</span> </a-col> <a-col :span="aRowCol.quantity"> <span>数量</span> </a-col> <a-col :span="aRowCol.discount"> <span>优惠</span> </a-col> <a-col :span="aRowCol.amount"> <span>小计</span> </a-col> <a-col :span="aRowCol.leftNum"> <span>残余数量</span> </a-col> </a-row> <div class="div-table-tbody" v-if="acData.length"> <div class="div-table-tbody-item" v-for="(item, index) in acData" :key="index"> <div class="tbody-item-title"> <a-checkbox v-model:checked="item.checked" @change="onChangeCheckedItemAll(item)"></a-checkbox> <span style="margin-left: 20px">{{ item.acName }}</span> </div> <a-row type="flex" align="middle" class="tbody-item-row" v-for="(i, ind) in item.acList" :key="ind"> <a-col :span="aRowCol.img"> <a-checkbox v-model:checked="i.checked" @change="onChangeChecked(item, i)" style="margin-right: 10px"></a-checkbox> <a-image style="width: 96px; height: 96px; border-radius: 5px; margin-right: 10px" :preview="false" :src="i.url ? i.url : ''" :fallback="fallImage" /> </a-col> <a-col :span="aRowCol.name" class="card-info"> <span>{{ i.skuName }}</span> <span class="font12 light-gray">{{ i.skuModel }}</span> </a-col> <a-col :span="aRowCol.price"> <span>¥{{ i.price }}</span> </a-col> <a-col :span="aRowCol.quantity"> <span>{{ i.totalNum }}</span> </a-col> <a-col :span="aRowCol.discount"> <span>¥{{ i.discountAmount }}</span> </a-col> <a-col :span="aRowCol.amount"> <span>¥{{ i.amount }}</span> </a-col> <a-col :span="aRowCol.leftNum"> <span>{{ i.leftNum }}</span> </a-col> </a-row> </div> </div> </div></template><script setup>import { ref } from "@vue/reactivity"// 图片占位符const fallImage = ''const aRowCol = ref({ img: 4, name: 5, quantity: 3, price: 3, discount: 3, amount: 3, leftNum: 3})const acData = ref([ { acName: '第一个分组', acId: 1, acList: [{ url: null, rowId: '1', skuName: '1-1 子分组的名字', skuCode: '1-1的id', skuModel: '类型类型类型类型类型类型11111型', price: 100.00, totalNum: 2, discountAmount: 100.00, leftNum: 1, amount: 100.00, acType: null, acName: "普通商品", acId: 1 }, { url: null, rowId: '1', skuName: '1-2 子分组的名字', skuCode: '1-2的id', skuModel: '类型类型类型类型类型类型类型类型111111', price: 200.00, totalNum: 1, discountAmount: 100.00, leftNum: 1, amount: 300.00, acType: null, acName: "普通商品", acId: 1 }] }, { acName: '第2个分组', acId: 2, acList: [{ url: null, rowId: '2', skuName: '2-1 子分组的名字', skuCode: '2-1的id', skuModel: '类型类型类型222222222222', price: 100.00, totalNum: 2, discountAmount: 50.00, leftNum: 1, amount: 250.00, acName: '第2个分组', acId: 2 }, { url: null, rowId: '2', skuName: '2-2 子分组的名字', skuCode: '2-2的id', skuModel: '类型类型类型类型类型类222', price: 50.00, totalNum: 1, discountAmount: 0.00, leftNum: 0, amount: 100.00, acName: '第2个分组', acId: 2 }] }])const checkedAll = ref(false)const checkedList = ref([])// 数组去重const uniqueArr = arr => { const obj = {} // 辅助数组 return arr.reduce((sum, idx) => { if (!obj[idx.rowId]) { // 判断以后orderRowId是否曾经在checkedList外面 // 如果不在 obj[idx.rowId] = true // 则将以后orderRowId的值设置为true(也能够是其余 sum.push(idx) // 而后push进以后的数组 } return sum }, [])}// 是否全选(只依据流动类型全选可用)const isCheckedAll = itemData => { // 全选 checkedList与addCommodityData雷同 const tempList = [] checkedList.value.forEach(item => { const sameItemIdx = acData.value.findIndex(a => a.acName == item.acName) // 比照原数组与选中数组各项的长度是否一样 tempList.push( acData.value[sameItemIdx].acList.length == item.acList.length ) }) const uncheckLen = tempList.findIndex(item => item == false) // 找出长度不统一的值 if (itemData.checked && checkedList.value.length == acData.value.length && uncheckLen < 0) { // 只有与原数组各项长度保持一致能力选中全选 return true } else if (itemData.checked && itemData.acList.length == 6) { // 以后流动的长度与后盾以后页面长度(假如页面长度为6)一样 return true } else if ( itemData.checked && acData.value.length == 1 && itemData.acList.length == acData.value[0].acList.length ) { // 以后流动所有数据与接口返回数据长度一样且接口返回只有一个数组 return true } else { return false }}// 全选const onChangeCheckedAll = all => { acData.value && acData.value.map(item => { item.checked = all.target.checked item.acList.map(i => { i.checked = all.target.checked }) }) if (all.target.checked) { // 选中 // 比拟checkedList与acData是否有雷同分组 if (checkedList.value.length > 0) { const tempList = JSON.parse(JSON.stringify(acData.value)) // 深拷贝数组 checkedList.value.forEach((item, index) => { tempList.forEach(i => { // 比拟checkedList与acData是否有雷同流动,属于雷同流动,增加进对应的流动中 if (i.acId == item.acId) { checkedList.value[index].acList = [...checkedList.value[index].acList, ...i.acList] // 数组去重操作 checkedList.value[index].acList = uniqueArr(checkedList.value[index].acList) } else { checkedList.value.push(i) } }) }) } else { // 第一次勾选,checkedList为空 checkedList.value = JSON.parse(JSON.stringify(acData.value)) // 深拷贝数组,第一次勾全选 } } else { // 勾销选中 // 比拟acList与checkedList的长度值,如果checkedList长度大于acList,勾销勾选,就从checkedList里删掉acList checkedList.value.forEach(item => { const sameItemIdx = acData.value.findIndex(a => a.acId == item.acId) // 比照原数组与选中数组各项的长度是否一样 if (acData.value[sameItemIdx].acList.length == item.acList.length) { checkedList.value = [] } else { // 找到匹配的数据,删除 acData.value[sameItemIdx].acList.forEach(a => { item.acList.map((i, ind) => { if (i.rowId == a.rowId) { item.acList.splice(ind, 1) } }) }) } }) } console.log('all', checkedList.value)}// 依据分组全选const onChangeCheckedItemAll = itemData => { const hasItemIdx = checkedList.value.findIndex(item => item.acId == itemData.acId) console.log('hasItemIdx', hasItemIdx) if (itemData.checked) { // 如果之前有选中项 itemData.acList.map(item => { item.checked = true }) const copyArr = JSON.parse(JSON.stringify(itemData)) // 深拷贝 if (hasItemIdx < 0) { // 从未有选中的数据 checkedList.value.push(copyArr) } else { // 之前曾经有选中的数据 checkedList.value.forEach((item, index) => { copyArr.acList.forEach(i => { if (copyArr.acId == item.acId) { checkedList.value[index].acList = [...checkedList.value[index].acList, i] // 数组去重操作 checkedList.value[index].acList = uniqueArr(checkedList.value[index].acList) } }) }) } checkedAll.value = isCheckedAll(itemData) } else { itemData.acList.map(item => { item.checked = false }) if (checkedList.value[hasItemIdx].acList.length == itemData.acList.length) { checkedList.value.splice(hasItemIdx, 1) } else { itemData.acList.forEach(a => { checkedList.value[hasItemIdx].acList.forEach((b, idx) => { if (b.rowId == a.rowId) { checkedList.value[hasItemIdx].acList.splice(idx, 1) } }) }) } checkedAll.value = false } console.log('huodong', checkedList.value)}// 单个选中const onChangeChecked = (itemData, iData) => { const itemIdx = checkedList.value.findIndex(item => item.acName == itemData.acName) let iIdx if (itemIdx > -1) { iIdx = checkedList.value[itemIdx].acList.findIndex(i => i.rowId == iData.rowId) } if (iData.checked) { // 选中 if (itemIdx > -1) { checkedList.value[itemIdx].acList.push(iData) } else { checkedList.value.push({ acName: itemData.acName, acId: itemData.acId, acList: [iData] }) } // 勾选操作 if (itemData.acList.length == 1) { itemData.checked = true } else if (itemData.acList.length > 1) { if (itemIdx > -1 && checkedList.value[itemIdx].acList.length == itemData.acList.length) itemData.checked = true } checkedAll.value = isCheckedAll(itemData) } else { // 勾销选中 if (itemIdx > -1) { if (checkedList.value.length == 1) { checkedList.value[0].acList.length == 1 ? (checkedList.value = []) : checkedList.value[itemIdx].acList.splice(iIdx, 1) } else if (checkedList.value.length > 1) { checkedList.value[itemIdx].acList.length == 1 ? checkedList.value.splice(itemIdx, 1) : checkedList.value[itemIdx].acList.splice(iIdx, 1) } } iData.checked = false checkedAll.value = false itemData.checked = false } console.log('www', checkedList.value)}</script>