vue+element 点击单元格就能修改数据,来学习一下吧【分享代码】

需求

客户需求多变,原先数据库表不再满足需求,需要被拆解并且表格之间映射关系多对多。
对于前端,需要提供一种修改方式,让用户修正将近1000条数据,并且要让用户感到高效

实现效果总览

点击单元格,就能让单元格变为input,并存储用户修改
在这里插入图片描述

实现步骤

分析需求

1、首先排除“点击一行,跳出窗口,修改一行保存”的模式,这对用户来说太慢
2、不可以一次加载/改变较多的dom元素
3、在页面不卡的情况下,尽可能多的展示数据

引入pl-table

pl-table是基于element组件的,其对el-table做了很多优化,其中仅对页面展示区域做渲染,大大提高了性能。
例如:现在一页有30行,原先肯定是一次性渲染好30行数据,向下滚动的时候卡顿的概率高;引入pl-table后,只展示页面能看见的10条数据,性能瞬间提升了一半多。

cnpm i pl-table
import { PlTable, PlTableColumn } from 'pl-table'

点击单元格触发修改事件

1、每一个单元格,都设置一个独有的ref,ref值为列数 + 某行数据的id,即’inputColumn1’+ scope.row.id
2、设置一个全局唯一的参数editdes记录点击的单元格的ref
3、当editdes与当前点击的单元格的ref一致时,将这个单元格变为input框;其余的正常显示
4、当input框处于blur状态下,将editdes清空,刚刚的input框又变为普通数据

       <pl-table
          ref="multipleTable"
          :data="tableData"
          border
          tooltip-effect="dark"
          :header-cell-style="{textAlign: 'center'}"
          :highlight-current-row="true"
          :use-virtual="true"
          :row-height="60"
          :height="700"
          @selection-change="handleSelectionChange">
          <pl-table-column type="selection" width="55" align="center"></pl-table-column>
          <pl-table-column label="data1" width="120">
            <template slot-scope="scope">
              <div class="cell-input-wrap">
                <el-input v-if="editdes === 'inputColumn1'+ scope.row.id" v-model.trim="scope.row.data1" :ref="'inputColumn1'+ scope.row.id" @blur="levelDesIt(scope.row)"></el-input>
                <div v-else @click="switchDesState('inputColumn1',scope.row.id)" class="default-span">{{scope.row.data1}}</div>
              </div>
            </template>
          </pl-table-column>
        </pl-table>

注意点

1、“<el-input v-if="editdes =”此处使用v-if来初始化数据,比v-show更快,因为那么多单元格,修改的地方应该不足30%,且不会修改多次。
2、当有多列参数时,建议一行行书写,而不是循环。因为数据一定会带有自己的规则(最大最小值,时间、正则等)
3、点击单元格触发的switchDesState函数,首先会校验是否为编辑模式,不是则点击无效

代码

vue代码

<template>
    <div>
      <div style="display: flex;justify-content: space-around;">
        <el-switch v-model="isEditMode" active-text="修改模式打开" inactive-text="关闭"></el-switch>
        <el-switch v-model="isTestPerformance" active-text="测试性能模式打开" inactive-text="关闭" @change="resetTableData"></el-switch>
      </div>
      <div>
        <pl-table
          ref="multipleTable"
          :data="tableData"
          border
          tooltip-effect="dark"
          :header-cell-style="{textAlign: 'center'}"
          :highlight-current-row="true"
          :use-virtual="true"
          :row-height="60"
          :height="700"
          @selection-change="handleSelectionChange">
          <pl-table-column type="selection" width="55" align="center"></pl-table-column>
          <!-- <pl-table-column label="data1" width="120">
            <template slot-scope="scope">
              <div class="cell-input-wrap">
                <el-input v-if="editdes === 'inputColumn1'+ scope.row.id" v-model.trim="scope.row.data1" :ref="'inputColumn1'+ scope.row.id" @blur="levelDesIt(scope.row)"></el-input>
                <div v-else @click="switchDesState('inputColumn1',scope.row.id)" class="default-span">{{scope.row.data1}}</div>
              </div>
            </template>
          </pl-table-column> -->
          <!-- 测试性能 -->
          <pl-table-column v-for="(item,index) in tableData" :key="item.id" :label="'data' + index" width="120">
            <template slot-scope="scope">
              <div class="cell-input-wrap">
                <el-input v-if="editdes === 'inputColumn'+ index + scope.row.id" v-model.trim="scope.row['data' + index]" :ref="'inputColumn'+ index + scope.row.id" @blur="levelDesIt(scope.row)" ></el-input>
                <div v-else @click="switchDesState('inputColumn' + index,scope.row.id)" class="default-span">{{scope.row['data' + index]}}</div>
              </div>
            </template>
          </pl-table-column>
        </pl-table>
      </div>
        <div style="margin-top: 20px">
          <el-button @click="toggleSelection()">取消选择</el-button>
        </div>
    </div>
</template>

<script>
import { _tableData } from './js/tableData.js'
import { PlTable, PlTableColumn } from 'pl-table'
export default {
  props: {},
  components: {
    PlTable,
    PlTableColumn
  },
  data() {
    return {
      isEditMode: true, // 是否开启编辑模式
      tableData: _tableData,
      multipleSelection: [],
      editdes: null, //标识处于编辑状态的单元格ref
      isTestPerformance:true // 是否为测试性能模式
    };
  },
  computed: {},
  created() {
    this.resetTableData()
  },
  mounted() {

  },
  watch: {},
  methods: {
    // 根据需求,展示简单/复杂的表格
    resetTableData() {
      this.isTestPerformance ? this.initManyData() : this.tableData = _tableData
    },
    toggleSelection(rows) {
      console.log(rows,'rows')
      if (rows) {
        rows.forEach(row => {
          console.log(row)
          this.$refs.multipleTable.toggleRowSelection(row);
        });
      } else {
        this.$refs.multipleTable.clearSelection();
      }
    },
    handleSelectionChange(val) {
      this.multipleSelection = val;
    },
    // 双击span会触发次函数,赋值使得编辑状态开启,row.id为唯一的,不会出现点击一个编辑框,其他也受到影响的情况出现
    switchDesState(val,id) {
      if(!this.isEditMode) return
      this.editdes = val + id;
      this.$nextTick(()=>{
        this.$refs[this.editdes][0].focus()
        // if(this.isTestPerformance){
        //   this.$refs[this.editdes][0].focus()
        // } else {
        //   this.$refs[this.editdes].focus()
        // }
      })
    },
    // 当input框失去焦点时,会触发此函数,使得此编辑状态关闭
    levelDesIt(row) {
      this.editdes = null;
    },
    // 初始化一个庞大的表格数据,i为行数,j为列数
    initManyData() {
      this.tableData = []
      let array = []
      for(let i = 0;i<=50;i++) {
        const obj = { id: i}
        for(let j = 0;j<=20;j++) {
          obj['data' + j] = `${i}行${j}列`
        }
        array.push(obj)
      }
      this.tableData = array
    }
  }
};
</script>

<style scoped lang="less">
/deep/.el-table .cell {
  line-height: 40px;
  .cell {
    padding: 0;
    display: flex;
    justify-content: center;
    align-items: center;
    margin: 0;
    height: 40px;
  }
  .default-span {
    display: block;
    height: 40px;
    width: 100%;
  }
  .el-input__inner {
    margin: 0;
  }
}
</style>

js

const _tableData = [
  {
    id: 1,
    date: '2016-05-03',
    name: '王小虎',
    address: '上海市普陀区金沙江路 1518 弄',
    data0: '11',
    data1: '12'
  },
  {
    id: 2,
    date: '2016-05-02',
    name: '王小虎',
    address: '上海市普陀区金沙江路 1518 弄',
    data0: '21',
    data1: '22'
  }
]

export { _tableData }

最后

如果对您有帮助,希望能给个👍评论收藏三连!

  • 3
    点赞
  • 11
    收藏
  • 打赏
    打赏
  • 1
    评论

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:游动-白 设计师:我叫白小胖 返回首页
评论 1

打赏作者

mmmmmmmmzw

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值