需求
假如这里有多个卡片,点击相应卡片之后需要提交卡片内信息,我们需要把点击的卡片筛选出来,在不使用组件库的前提下实现全选,多选,单选操作(其中全选和多选为一个需求,单选为一个需求)
全选+多选
思路
首先我们需要给全选设置一个状态(showAllSelected),用此状态来控制全显是否点击。那怎么控制每个卡片的状态呢?由于数据是后端请求得到,我们需要对请求的数据进行改造,添加checked属性来控制是否点击每个卡片。
代码实现
HTML
xml
<!-- 多选 -->
<template>
<div style="display: flex">
<span>全选</span>
<span
:style="{
backgroundColor: showAllSelected ? '#009aff' : '#fff',
borderColor: showAllSelected ? 'transparent' : 'black',
}"
class="circle"
@click="handleselectedAll"
>{{ showAllSelected ? '√' : '' }}</span
>
</div>
<div class="item-detail" v-for="(tmp, index) in itemData" :key="index">
<div class="module-item">
<span>序号:{{ tmp.flowOrder }}</span>
<span
:style="{
backgroundColor: tmp.checked ? '#009aff' : '#fff',
borderColor: tmp.checked ? 'transparent' : 'black',
}"
class="circle"
@click="handleMultiple(index)"
>{{ tmp.checked ? '√' : '' }}</span
>
</div>
</div>
</template>
首先对后端请求数据进行改造,为每个item添加checked属性
ini
handleData() {
let returnData = [
{
flowOrder: 1,
},
{
flowOrder: 2,
},
{
flowOrder: 3,
},
]
returnData.forEach((item) => {
item.checked = false
})
this.itemData = returnData
},
全选
showAllSelected: false, 用来控制全选。
当点击全选时,首先对全选状态取反,当我们第一次点击全选,下面的子项要全部选中,再次点击全选,子项也要改变,所以子项的状态和全选状态完全一致,直接对每个子项赋值为全选的状态即可。
javascript
// 全选
handleselectedAll() {
// 每次点击将选择框状态改变为全选状态即可
this.showAllSelected = !this.showAllSelected
this.itemData.forEach((item) => {
item.checked = this.showAllSelected
})
},
点击全选之后的效果
再次点击效果
可以看到全选多次点击效果已经实现了~
多选
多选就是去点击每个子项,子项之间互相不干扰。注意当子项全部被选中时,全选也要被选中, 子项没有被全部选中时,全选状态为false。
当选中当前子项,对当前子项的状态进行取反。
每次点击都要判断是否所有的子项被选中,对每次判断状态赋值给全选的状态即可,every函数功能为只有当所有条件成立才会返回true,有一项不成立就返回false,符合我们的需求。
javascript
// 多选
handleMultiple(index) {
// 点击将相应状态改变
this.itemData[index].checked = !this.itemData[index].checked
// 每次点击判断是否全部选中,将状态赋值给
let isSelectedAll = this.itemData.every((item) => item.checked)
this.showAllSelected = isSelectedAll
},
没有全部选中
全部选中
我们看到多选状态也实现了。同时全选状态也会跟着变化呢~
提交
点击提交之后拿到相应数据,只需要把 checked 为true的筛选出来即可。
javascript
// 提交
submit() {
let data = this.itemData.filter((item) => item.checked)
console.log('data: ', data)
},
单选
思路
单选和多选不一致,每次只能点击一个,再次点击当前的,需要状态取反。
因为第二次不一定点击当前这个还是其他的,所有需要设置一个currentIndex来标识是不是当前index,如果是就进行取反,如果不是就让先让所有的状态取消,设置当前状态为true即可。
代码实现
HTML
xml
<!-- 单选 -->
<template>
<div class="item-detail" v-for="(tmp, index) in itemData" :key="index">
<div class="module-item">
<span>序号:{{ tmp.flowOrder }}</span>
<span
:style="{
backgroundColor: tmp.checked ? '#009aff' : '#fff',
borderColor: tmp.checked ? 'transparent' : 'black',
}"
class="circle"
@click="handleSingle(index)"
>{{ tmp.checked ? '√' : '' }}</span
>
</div>
</div></template
>
currentIndex 标识当前 index
kotlin
handleSingle(index) {
// 如果是当前项取反
if (this.currentIndex === index) {
this.itemData[index].checked = !this.itemData[index].checked
} else {
// 不是先取消所有状态
this.itemData.forEach((item) => {
item.checked = false
})
// 当前项设置为true
this.itemData[index].checked = true
}
//记录当前index
this.currentIndex = index
},
效果
提交
点击提交之后拿到相应数据,只需要把checked为true的筛选出来即可。
javascript
// 提交
submit() {
let data = this.itemData.filter((item) => item.checked)
console.log('data: ', data)
},
我们看到单选效果也实现了~
所有源码
这里附上全部代码,感兴趣的小伙伴可以自己试试,如果感觉对你有帮助,可以给作者点下赞呢~
xml
<template>
<div>
<!-- 多选 -->
<template v-if="false">
<div style="display: flex">
<span>全选</span>
<span
:style="{
backgroundColor: showAllSelected ? '#009aff' : '#fff',
borderColor: showAllSelected ? 'transparent' : 'black',
}"
class="circle"
@click="handleselectedAll"
>{{ showAllSelected ? '√' : '' }}</span
>
</div>
<div class="item-detail" v-for="(tmp, index) in itemData" :key="index">
<div class="module-item">
<span>序号:{{ tmp.flowOrder }}</span>
<span
:style="{
backgroundColor: tmp.checked ? '#009aff' : '#fff',
borderColor: tmp.checked ? 'transparent' : 'black',
}"
class="circle"
@click="handleMultiple(index)"
>{{ tmp.checked ? '√' : '' }}</span
>
</div>
</div>
</template>
<!-- 单选 -->
<template>
<div class="item-detail" v-for="(tmp, index) in itemData" :key="index">
<div class="module-item">
<span>序号:{{ tmp.flowOrder }}</span>
<span
:style="{
backgroundColor: tmp.checked ? '#009aff' : '#fff',
borderColor: tmp.checked ? 'transparent' : 'black',
}"
class="circle"
@click="handleSingle(index)"
>{{ tmp.checked ? '√' : '' }}</span
>
</div>
</div></template
>
</div>
</template>
<script>
export default {
name: 'DataTest',
data() {
return {
itemData: [],
showAllSelected: false,
currentIndex: -1,
}
},
created() {
this.handleData()
},
methods: {
// 多选
handleMultiple(index) {
// 点击将相应状态改变
this.itemData[index].checked = !this.itemData[index].checked
// 每次点击判断是否全部选中,将状态赋值给
let isSelectedAll = this.itemData.every((item) => item.checked)
this.showAllSelected = isSelectedAll
},
// 全选
handleselectedAll() {
// 每次点击将选择框状态改变为全选状态即可
this.showAllSelected = !this.showAllSelected
this.itemData.forEach((item) => {
item.checked = this.showAllSelected
})
},
// 单选
handleSingle(index) {
// 如果是当前项取反
if (this.currentIndex === index) {
this.itemData[index].checked = !this.itemData[index].checked
} else {
// 不是先取消所有状态
this.itemData.forEach((item) => {
item.checked = false
})
// 当前项设置为true
this.itemData[index].checked = true
}
//记录当前index
this.currentIndex = index
},
// 初始化数据
handleData() {
let returnData = [
{
flowOrder: 1,
},
{
flowOrder: 2,
},
{
flowOrder: 3,
},
]
returnData.forEach((item) => {
item.checked = false
})
this.itemData = returnData
},
},
}
</script>
<style scoped>
.module-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px;
margin: 10px;
border: 1px solid #409eff;
border-radius: 8px;
}
.circle {
display: flex;
justify-content: center;
align-items: center;
border-width: 1px;
border-style: solid;
border-radius: 50%;
color: #fff;
width: 20px;
height: 20px;
margin-left: 10px;
line-height: 35px;
text-align: center;
}
</style>