Vue 实现全选、多选、单选效果

需求

假如这里有多个卡片,点击相应卡片之后需要提交卡片内信息,我们需要把点击的卡片筛选出来,在不使用组件库的前提下实现全选,多选,单选操作(其中全选和多选为一个需求,单选为一个需求)

全选+多选

思路

首先我们需要给全选设置一个状态(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>

相关推荐
树上有只程序猿25 分钟前
Go Web服务中如何优雅平滑重启?
前端·golang·xcode
思考的Joey32 分钟前
一种纯前端的H5灰度方案
前端·javascript
几何心凉34 分钟前
网页抓取API,让数据获取更简单
前端·webpack·node.js
代码老祖1 小时前
vue2 + iview(view-design) 中封装使用 vxe-table 处理表格渲染大量数据卡顿现象
前端·vue.js·view design·vxe-table
咔咔库奇2 小时前
CSS基础知识01
前端·css
missingzlp2 小时前
HTML and CSS Support HTML 和 CSS 支持
前端·css·html
Sword992 小时前
LangChain 实战08 - OutputParser
前端·人工智能·豆包marscode
乐多_L2 小时前
axios的post请求,数据为什么要用qs处理?什么时候不用?
前端·javascript·vue.js
Stanford_11062 小时前
C++入门基础知识150—【关于C++ 输入/输出运算符重载】
前端·javascript·c++·微信小程序·微信公众平台·twitter·微信开放平台
Domain-zhuo2 小时前
css3的新特性有哪些?
前端·css·css3