|
1 | 1 | <template> |
2 | 2 | <div> |
3 | | - <div>other3</div> |
| 3 | + <div v-for="(group, index) in groupList" :key="group.groupName + index"> |
| 4 | + <!-- 组复选框 --> |
| 5 | + <el-checkbox v-model="group.selected" :indeterminate="isIndeterminate(group)" @change="handleCheckAllChange(group, $event)"> |
| 6 | + {{ group.groupName }} |
| 7 | + </el-checkbox> |
| 8 | + |
| 9 | + <!-- 子项的 checkbox --> |
| 10 | + <div> |
| 11 | + <el-checkbox-group v-model="selectedList"> |
| 12 | + <div v-for="(item, index2) in group.itemList" :key="item.value + index2" style="padding-left: 20px"> |
| 13 | + <el-checkbox :label="item.label" :value="item.value" @change="handleCheckChange(group, index, $event)" /> |
| 14 | + </div> |
| 15 | + </el-checkbox-group> |
| 16 | + </div> |
| 17 | + <!-- 子项样式二 --> |
| 18 | + <div class="box-card"> |
| 19 | + <el-checkbox-group v-model="selectedList"> |
| 20 | + <span v-for="(item, index2) in group.itemList" :key="item.value + index2" style="padding-left: 20px"> |
| 21 | + <el-checkbox :label="item.label" :value="item.value" @change="handleCheckChange(group, index, $event)" /> |
| 22 | + </span> |
| 23 | + </el-checkbox-group> |
| 24 | + </div> |
| 25 | + </div> |
| 26 | + |
| 27 | + <div style="margin-top: 20px"> |
| 28 | + <el-button type="primary" @click="handleGetSelectedList">获取选中的值</el-button> |
| 29 | + </div> |
4 | 30 | </div> |
5 | 31 | </template> |
6 | 32 |
|
7 | | -<script setup lang="ts"></script> |
| 33 | +<script setup lang="ts"> |
| 34 | +type GroupItemType = { |
| 35 | + label: string |
| 36 | + value: string |
| 37 | +} |
| 38 | +
|
| 39 | +type GroupListType = { |
| 40 | + groupName: string |
| 41 | + selected: boolean |
| 42 | + itemList: GroupItemType[] |
| 43 | +} |
| 44 | +
|
| 45 | +const state = reactive({ |
| 46 | + groupList: [ |
| 47 | + { |
| 48 | + groupName: 'BB', |
| 49 | + selected: false, // 初始选中状态 |
| 50 | + itemList: [ |
| 51 | + { label: 'test name1', value: '11' }, |
| 52 | + { label: 'test name2', value: '22' }, |
| 53 | + { label: 'test name3', value: '33' }, |
| 54 | + { label: 'test name4', value: '44' }, |
| 55 | + { label: 'test name5', value: '55' } |
| 56 | + ] |
| 57 | + }, |
| 58 | + { |
| 59 | + groupName: 'AA', |
| 60 | + selected: false, // 初始选中状态 |
| 61 | + itemList: [ |
| 62 | + { label: 'test name6', value: '66' }, |
| 63 | + { label: 'test name7', value: '77' }, |
| 64 | + { label: 'test name8', value: '88' }, |
| 65 | + { label: 'test name9', value: '99' }, |
| 66 | + { label: 'test name10', value: '100' } |
| 67 | + ] |
| 68 | + } |
| 69 | + ] as GroupListType[], |
| 70 | + // 用于存储选中的 checkbox 值 |
| 71 | + selectedList: [] as string[] |
| 72 | +}) |
| 73 | +const { groupList, selectedList } = toRefs(state) |
| 74 | +
|
| 75 | +function handleCheckAllChange(group: GroupListType, selected: boolean) { |
| 76 | + // 选中时,将该组内所有 itemList 的 value 添加到 selectedList 中,注意去重 |
| 77 | + if (selected) { |
| 78 | + state.selectedList = [...new Set([...state.selectedList, ...group.itemList.map((item) => item.value)])] |
| 79 | + } else { |
| 80 | + // 取消选中时,将该组内所有 itemList 的 value 从 selectedList 中移除 |
| 81 | + state.selectedList = state.selectedList.filter((value) => !group.itemList.map((item) => item.value).includes(value)) |
| 82 | + } |
| 83 | +} |
| 84 | +// 判断当前组的复选框是否是部分选中(indeterminate) |
| 85 | +function isIndeterminate(group: GroupListType) { |
| 86 | + const itemList = group.itemList || [] |
| 87 | + const selectedInGroup = itemList.filter((item) => state.selectedList.includes(item.value)) |
| 88 | + return selectedInGroup.length > 0 && selectedInGroup.length < itemList.length |
| 89 | +} |
| 90 | +function handleCheckChange(group: GroupListType, index: number, selected: boolean) { |
| 91 | + // 更新当前组的 全选/取消全选 状态 |
| 92 | + group.selected = group.itemList.every((item) => state.selectedList.includes(item.value)) |
| 93 | +} |
| 94 | +function handleGetSelectedList() { |
| 95 | + console.log('selectedList', JSON.stringify(state.selectedList)) |
| 96 | +} |
| 97 | +</script> |
8 | 98 |
|
9 | | -<style lang="scss" scoped></style> |
| 99 | +<style lang="scss" scoped> |
| 100 | +.box-card { |
| 101 | + margin: 10px; |
| 102 | + padding: 10px 15px; |
| 103 | + border-radius: 5px; |
| 104 | + box-shadow: 0px 0px 5px 3px rgba(0, 0, 0, 0.1); |
| 105 | + border-bottom: 1px solid #e6e6e6; |
| 106 | +} |
| 107 | +</style> |
0 commit comments