基于element-ui table中多选框分页时的选择状态管理(二)

8 篇文章 0 订阅
4 篇文章 0 订阅

这篇是《基于element-ui table中多选框分页时的选择状态管理(一)》的优化版,大致需求就是实现用户在不同pageIndex中对table进行操作之后,只需点击一次确定按钮就能提交用户的每一个操作项,想了解具体需求可以查看第一版。

说得可能有点抽象,大家可以看一下下面这个图,用户在没提交的情况下可以在多个pageIndex中进行选择,点击确定按钮,提交所有pageIndex中操作过的选项(包括:1. 原来选中但提交时取消选中的,2. 原来未选中但提交时选中的

1. 原因

​ 虽然第一种方案也实现了产品的需求,但是我采取了禁用checkbox,只允许用户点击该行中除了checkbox以外的区域来实现对该行的选择,有点曲线救国的意思。

​ 还有一个原因就是,需求代码虽然已经合进master并放到线上了,但是,自己这种做法还是被我们技术经理约谈了,约谈了,约谈了…

​ 于是,打工人重开分支,开始优化…

2. 思路

​ 这一回肯定是不能禁用checkBox了,那我们就合理利用elementUI官方给出的multipleSelection属性吧,这里再花点时间解释一下这个属性:

multipleSelection是一个数组,表示table中当前pageIndex的所有选中项,我们每选中一项,multipleSelection中就会push进我们刚选中的项,而我们每取消一项,multipleSelection就会删除我们取消的那一项

​ 第二版我是这样设计的:

具体思路请看代码实现

3. 代码

template代码

<template>
  <div>
    <el-dialog width="900px" :visible="visible" title="公司权限" @close="updateVsible(false)">
      <el-table
        ref="multipleTable"
        :data="list"
        tooltip-effect="dark"
        style="width: 100%"
        @selection-change="handleSelectionChange"
        @row-click="handleRowClick"
      >
        <el-table-column
          type="selection"
          width="55"
        />
        <el-table-column
          prop="liveCompanyName"
          label="公司名"
        />
      </el-table>
      <el-pagination
        v-if="totalCount"
        :disabled="loading.list"
        :class="'db-pagination-size-' + pageSize"
        style="margin-top: 20px;"
        background
        layout="total, prev, pager, next"
        :current-page="pageIndex"
        :page-size="pageSize"
        :total="totalCount"
        @current-change="fetchList"
      />

      <span slot="footer">
        <el-button type="primary" @click="handleCreateClick">
          确定
        </el-button>
        <el-button @click="updateVsible(false)">
          取消
				</el-button>
      </span>
    </el-dialog>
  </div>
</template>

script功能代码:

<script>
export default {
  name: 'CompanyEditor',
  props: {
    visible: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      list: [],
      multipleSelection: [],
      totalCount: 0,
      pageIndex: 1,
      pageSize: 20,
      /** 临时改变的所有选中项 */
      changeListMap: new Map(),
      /** 接口返回的所有页面的数据 */
      allListMap: new Map()
    }
  },

  watch: {
    visible(newVal) {
      if (newVal) {
        this.initModal()
      }
    },
    /** 监听选中项的改变更新changListMap */
    multipleSelection(newVal) {
      this.changeListMap.set(this.pageIndex, newVal)
    }
  },
  methods: {
    initModal() {
      this.initParams()
      this.fetchList()
    },
    initParams() {
      this.pageIndex = 1
      this.list = []
      this.totalCount = 0
    },
    /**
     * 获取公司列表
     */
    async fetchList(pageIndex = this.pageIndex) {
      // 已经请求过的页面取allListMap中的数据,无需再次请求
      if (this.allListMap.get(pageIndex)) {
        this.fetchLocalList(pageIndex)
        return
      }

      // 这里请求接口得到响应数据res

      if (res?.success && res?.data?.list) {
        const { totalCount = 0, pageIndex, list = [] } = res.data
        this.list = list
        this.totalCount = totalCount
        this.pageIndex = pageIndex
				// 新获取的数据更新到allListMap
        this.allListMap.set(pageIndex, list)
				// 更新选中项
        this.$nextTick(() => {
          this.list.forEach(item => {
            this.$refs.multipleTable.toggleRowSelection(item, item.hasPermission)
          })
        })
      }
    },
    /** 获取map中的数据 */
    fetchLocalList(pageIndex = this.pageIndex) {
      // 取出当前页的数据
      this.list = this.allListMap.get(pageIndex)
      this.pageIndex = pageIndex
			// 取出当前页的选中项
      const currentList = this.changeListMap.get(pageIndex)
			// 更新选中项
      this.$nextTick(() => {
        currentList.forEach(el => {
          this.$refs.multipleTable.toggleRowSelection(el, true)
        })
      })
    },

    async handleCreateClick() {
      const { adminId, allListMap, changeListMap } = this
      const newAllListMap = [...allListMap.values()].flat()
      const newChangeListMap = [...changeListMap.values()].flat()
      const upList = []
      // 添加所有选中项到upList
      newChangeListMap.forEach(item => {
        upList.push({ liveCompanyId: item.liveCompanyId, hasPermission: true })
      })
      // 添加原本选中但取消选中的项到upList
      newAllListMap.forEach(el => {
        const { liveCompanyId, hasPermission } = el
        if (hasPermission) {
          const exist = newChangeListMap.findIndex(item => item.liveCompanyId === liveCompanyId) >= 0
          if (exist) return
          upList.push({ liveCompanyId, hasPermission: !hasPermission })
        }
      })

      // 请求接口提交upList
      // ...
    },
      
		// 提交或者取消,初始化两个map,关闭弹窗
    // 这里根据自己的实际业务,没有弹窗的可以不用关闭
    updateVsible(visible) {
      this.changeListMap = new Map()
      this.allListMap = new Map()
      this.$emit('update:visible', visible)
    },
      
		// 改变已选项列表
    handleSelectionChange(val, index) {
      this.multipleSelection = val
    },

    // 点击改变当前项选中状态
    handleRowClick(val) {
      const { multipleSelection } = this
      const { liveCompanyId } = val
      const exist = multipleSelection.findIndex(item => item.liveCompanyId === liveCompanyId) >= 0

      this.$refs.multipleTable.toggleRowSelection(val, !exist)
    }
  }
}
</script>

基本不需要style代码

4. 实现效果
  1. 初始化第一页数据,点击提交查看效果
    1. changListMap有1项,选中1项
    2. allListMap有1项,包含20条
    3. 提交包含1项,其状态为true
  2. 在第一页增加一个选中项,点击提交查看效果
    1. changListMap有1项,选中2项
    2. allListMap有1项,包含20条
    3. 提交包含2项,状态为2true
  3. 在第一页取消原本的选中项,点击提交查看效果
    1. changListMap有1项,选中1项
    2. allListMap有1项,包含20条
    3. 提交包含2项,状态为1true 1false
  4. 切换到第二页,点击提交查看效果
    1. changListMap有2项,每项各选中一个
    2. allListMap有2项,每项各20条
    3. 提交包含3项,状态为2true 1false (第一页新增一个,取消一个默认,第二页一个默认)
  5. 在第二页,新增两个选项,点击提交查看效果
    1. changListMap有2项,第一项选中1,第二项选中3
    2. allListMap有2项,每项各20条
    3. 提交包含3项,状态为4true 1false (第一页新增一个,取消一个默认,第二页一个默认,新增两个)
  6. 在第二页取消一个新增项,点击提交查看效果
    1. changListMap有2项,第一项选中1,第二项选中2
    2. allListMap有2项,每项各20条
    3. 提交包含3项,状态为3true 1false (第一页新增一个,取消一个默认,第二页一个默认,一个新增,原本新增的被取消)
  7. 返回第一页,点击提交查看效果
    1. changListMap有2项,第一项选中1,第二项选中2
    2. allListMap有2项,每项各20条
    3. 提交包含3项,状态为3true 1false (第一页新增一个,取消一个默认,第二页一个默认,一个新增,原本新增的被取消)
  8. 最后,在第一页再新增一项,点击提交查看效果
    1. changListMap有2项,第一项选中2,第二项选中2
    2. allListMap有2项,每项各20条
    3. 提交包含3项,状态为4true 1false (第一页新增两个,取消一个默认,第二页一个默认,一个新增,原本新增的被取消)
5.总结

​ 从上面的效果图可以看出,我们最后只要提交upList中的数据给后端就行,既实现了记住每页的操作记录,也减少了接口请求,比第一版提交的数据也少了不少,对性能优化还是起到了一些微乎其微的作用,哈哈

​ 虽然这一版相对于第一版确实优化了不少,但是可能还有更好的解决办法,或者我这第二版还能继续优化,如果小伙伴们有更好的办法,欢迎再评论区留言噢。。。

end~~

鉴于笔者水平有限,若本文存在不当之处欢迎指出噢

有疑问的小伙伴,欢迎在下方留言,笔者看到都会回复的

若未能及时回答,也可以选择加入前端应知应会交流群群提问噢~~

群号:216644014(前端应知应会)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值