最近有一个这样的需求:需要点击图片后实现单选的效果,再次点击该图片后取消选中
这里的实现方案大概有两种:
- 第一种就是利用 input元素和img元素,主要利用input元素的checked属性,具体的代码实现可参考我之前写的有关vue2实现:juejin.cn/post/728791…
- 第二种就是利用img元素以及数组的有关知识进行,这里着重介绍该种方法
实现效果如下:
思路:
- 为了能够实现这个类似于选中和取消选中的效果,这里需要对后台返回的数据加以处理,给每条数据增加一个isChecked: false,以此来初始化其选中与否的状态
<ImageCheckRadio :iconsList="iconsList" :itemsPerRow="8" @changeValueClick="changeValueClick"></ImageCheckRadio>
const iconsList = ref([]);
const changeValueClick = (val) => {
if (Object.keys(val).length !== 0) {
currentIconItem.value = val;
let id = currentIconItem.value.jrjg_id[0].id;
let jrjgname = currentIconItem.value.jrjgname;
iconBankParams.value =
'[{"id":"' + id + '","unitType":' + 1 + ',"name":"' + jrjgname + '"}]';
} else {
currentIconItem.value = [];
iconBankParams.value = "";
}
queryParams.value.pageSize = 10;
// 请求数据
getInstitutionProductsListTwo();
};
// 请求数据
const getLoanInstitutionImg = () => {
...
if (res.code == 200) {
iconsList.value = res.data.sort(
(a, b) => a.data.order_by - b.data.order_by
);
iconsList.value.forEach((v) => {
v.bg_img = proxy.$imgUrl + v.data.img[0].refId;
v.isCheck = false;
v.checkOrder = 0;
});
}
}
子组件:ImageCheckRadio.vue
<template>
<div class="image-checked-container">
<div style="display: flex; align-items: center; flex-wrap: wrap">
<div
v-for="(item, index) in displayedIcons"
:key="index"
:class="{ checked: item.isCheck }"
style="
width: 122px;
height: 39px;
margin-right: 15px;
margin-bottom: 10px;
margin-top: 10px;
"
>
<img
:src="item.bg_img"
class="img"
alt="Radio Image"
@click="currentBankClickHandle(item)"
/>
</div>
</div>
<div class="tools">
<p
v-if="!showAll && iconsList.length > itemsPerRow"
@click="showAll = true"
style="
cursor: pointer;
padding-right: 20px;
text-align: left;
color: #578cf0;
font-size: 15px;
"
class="flex-column-center"
>
<span style="padding-right: 5px; padding-left: 2px">...</span>
<span>加载更多</span>
</p>
<p
v-else-if="showAll && iconsList.length > itemsPerRow"
@click="showAll = false"
style="
cursor: pointer;
padding-right: 20px;
text-align: left;
color: #578cf0;
font-size: 15px;
"
class="flex-column-center"
>
<el-icon><Top /></el-icon>
收起
</p>
</div>
</div>
</template>
<script setup>
import { ref, computed } from "vue";
const props = defineProps({
iconsList: {
type: Array,
default: () => [],
},
itemsPerRow: {
type: Number,
default: 8,
},
});
const emits = defineEmits(["changeValueClick"]);
const showAll = ref(false);
// 控制 加载更多/收起
const displayedIcons = computed(() => {
if (showAll.value) {
return props.iconsList;
} else {
// 只显示前itemsPerRow个项目
return props.iconsList.slice(0, props.itemsPerRow);
}
});
// 图片选中与取消选中
const chooseList = ref([]);
const currentBankClickHandle = (item) => {
// 多选逻辑
// // 选中
// if (!item.isCheck) {
// chooseList.value.push(item);
// // 修改状态
// item.isCheck = true;
// return;
// }
// // 取消选中
// // 找到在chooseList中的索引,
// let i = chooseList.value.findIndex((v) => v.id == item.id);
// if (i === -1) return;
// // 删除
// chooseList.value.splice(i, 1);
// // 修改状态
// item.isCheck = false;
// console.log('多选', chooseList.value);
// 单选逻辑
// // 取消所有已选中的图片
// chooseList.value.forEach((v) => {
// v.isCheck = false;
// });
// // 清空已选中的图片列表
// chooseList.value = [];
// // 选中当前点击的图片
// item.isCheck = true;
// chooseList.value.push(item);
// 单选逻辑--当再次点击选中图片时会处于未选中状态
// 如果当前图片已经被选中,则取消选中并清空chooseList数组
if (item.isCheck) {
item.isCheck = false;
chooseList.value = [];
emits("changeValueClick", {});
// console.log('单选', chooseList.value);
return;
}
// 取消所有已选中的图片
chooseList.value.forEach((v) => {
v.isCheck = false;
});
// 清空已选中的图片列表
chooseList.value = [];
// 选中当前点击的图片
item.isCheck = true;
chooseList.value.push(item);
emits("changeValueClick", item.data);
// console.log('单选', chooseList.value);
};
</script>
<style scoped lang="scss">
.image-checked-container {
width: 1200px;
height: 100%;
margin: 0 auto;
overflow: hidden;
box-sizing: border-box;
position: relative;
.img {
width: 120px;
height: 37px;
border: 1px solid #ccc;
cursor: pointer;
}
.tools {
position: absolute;
right: 20px;
top: 15px;
font-size: 14px;
}
.checked {
border: 1px solid red;
}
}
</style>