Vue.js实现可编辑表格并高亮修改的单元格

实现一个可编辑的表格,让用户可以修改表格中的数据,并且能够清楚地看到哪些单元格被修改过。这样的功能可以提高用户体验,也方便后端处理数据的变化。

本文将介绍如何使用Vue.js和Element UI的el-table组件来实现一个可编辑表格,并且修改的单元格会有不同的背景色。
Vue.js实现可编辑表格并高亮修改的单元格_第1张图片

代码实现

首先创建一个el-table组件,给它绑定一个data属性,用来存储表格的数据。给每个el-table-column设置一个prop属性,用来指定每一列对应的数据字段。使用v-for指令来动态生成表格的列,根据一个tableColumn数组,里面存储了每一列的信息,比如label,prop,fixed等。可以给el-table添加一些事件监听,比如cell-mouse-enter,cell-mouse-leave,cell-click等,用来实现鼠标移入移出和点击单元格的效果。代码如下:

<el-table ref="multipleTable"  stripe :border=true :data="tableData"
            @cell-mouse-enter="handleCellEnter" @cell-mouse-leave="handleCellLeave" @cell-click="handleCellClick"
            :cell-style="cellstyle">
            <el-table-column width=120 v-for="column in tableColumn" :key="column.aliasColName"
              :prop="column.aliasColName" :label="column.text" :fixed="column.fixed">
              <div class="item" v-if="column.editStyle == 5"
                slot-scope="scope">
                <el-input class="item__input"  v-model="scope.row[scope.column.property]" placeholder="请输入内容">
               <i slot="suffix" class="el-icon-edit" @click="showPwd(scope.row, scope.$index, scope.column)">i>
                el-input>
                <div class="item__txt">{{ scope.row[scope.column.property] }}div>
              div>
              <div class="item" v-else-if="column.editStyle == 22" slot-scope="scope">
                <el-select v-model="scope.row[scope.column.property]" placeholder="请选择">
                  <el-option v-for="item in listArray" :key="item.value" :label="item.display" :value="item.value">
                  el-option>
                el-select>
              div>
            el-table-column>
            <el-table-column fixed="right" label="操作" width="120" v-if="!visremove">
              <div class="item" slot-scope="scope">
                <el-popconfirm confirm-button-text='好的' cancel-button-text='取消' icon="el-icon-info" icon-color="red"
                  title="确定删除吗?" @confirm="removerow(scope.row)">
                  <el-button slot="reference" type="text" size="small">删除el-button>
                el-popconfirm>
              div>
            el-table-column>
          el-table>

接下来需要在data中定义一些变量,用来存储表格的数据,列的信息,下拉框的选项,以及一些控制变量,比如clickSwitch,用来记录当前点击的单元格,clickCellMap,用来存储当前点击的单元格的DOM元素,tableDataCopy,用来存储表格数据的副本,用于和修改后的数据进行对比。代码如下:

data() {
      return {
        tableData: [], //表格数据
        tableColumn: [], //表格列信息
        listArray: [], //下拉框选项
        clickSwitch: { //当前点击的单元格
          row: "",
          col: ""
        },
        clickCellMap: [], //当前点击的单元格的DOM元素
        tableDataCopy: [], //表格数据的副本
      };
    },

然后,需要在mounted中调用一个loadtabledata方法,用来加载表格的数据和列的信息。这里使用了一个模拟的数据文件loadData.json,里面存储了表格的数据和列的信息。根据实际的需求,从后端获取数据或者自定义数据。还需要使用JSON.parse和JSON.stringify方法,来创建一个表格数据的副本,用于后续的对比。代码如下:

mounted() {
      this.loadtabledata();
    },
    methods: {
      //表格
      loadtabledata() {
        let resloadtabledata = require("@/artificialdata/loadData.json")
        this.tableData = resloadtabledata.data.data
        this.tableDataCopy = JSON.parse(JSON.stringify(resloadtabledata.data.data))
      },
    }

接下来实现一些事件处理的方法,用来实现鼠标移入移出和点击单元格的效果。handleCellEnter方法用来处理鼠标移入单元格的事件。获取当前单元格的column和cell,然后判断是否有prop属性,如果有,说明是可编辑的单元格,就给它的item__txt类添加一个item__txt–hover类,用来显示一个编辑图标,提示用户可以点击编辑。代码如下:

/** 鼠标移入cell */
    handleCellEnter(row, column, cell, event) {
      const property = column.property
      if (property) {
        cell.querySelector('.item__txt').classList.add('item__txt--hover')
      }
    },

然后,需要实现一个handleCellLeave方法,用来处理鼠标移出单元格的事件。需要获取当前单元格的column和cell,然后判断是否有prop属性,如果有,说明是可编辑的单元格,就给它的item__txt类移除一个item__txt–hover类,用来隐藏编辑图标。代码如下:

/** 鼠标移出cell */
    handleCellLeave(row, column, cell, event) {
      const property = column.property
      if (property) {
        cell.querySelector('.item__txt').classList.remove('item__txt--hover')
      }
    },

接下来,实现一个handleCellClick方法,用来处理点击单元格的事件。获取当前单元格的row,column,cell,然后判断是否是同一个单元格,如果是,就不做任何操作,如果不是,就记录当前点击的单元格的信息,存储到clickSwitch变量中。然后,需要判断是否有之前点击的单元格,如果有,就触发它的失焦事件,让它保存数据,并且切换它的显示状态,让它显示文本,隐藏输入框。最后,切换当前点击的单元格的显示状态,让它显示输入框,隐藏文本,并且让输入框获取焦点。代码如下:

/** 点击cell */
    handleCellClick(row, column, cell, event) {
      if (this.clickSwitch.row == row.id && this.clickSwitch.col == column.property) {
        return
      }
      this.clickSwitch.row = row.id
      this.clickSwitch.col = column.property

      const property = column.property
      // 保存cell
      if (this.clickCellMap.length > 0 ) {
        this.clickCellMap[0].querySelector('input').blur()
      }
      if (this.clickCellMap.length > 0) {
        this.clickCellMap[0].querySelector('.item__txt').style.display = 'block'
        this.clickCellMap[0].querySelector('.item__input').style.display = 'none'
      }
     
        this.clickCellMap[0]=cell
        cell.querySelector('.item__txt').style.display = 'none'
        cell.querySelector('.item__input').style.display = 'block'
        cell.querySelector('input').focus()
      
    },

最后实现一个cellstyle方法,用来设置单元格的样式。需要获取当前单元格的row,column,rowIndex,columnIndex,然后判断当前单元格的值是否和表格数据副本中的值相同,如果不同,就说明该单元格被修改过,就给它返回一个背景色的样式,比如"background-color: rgb(144 199 255);",让它显示为蓝色。这样,用户就可以一眼看出哪些单元格被修改过,哪些没有。代码如下:

cellstyle({ row, column, rowIndex, columnIndex }) {
      if (this.tableDataCopy[rowIndex][column.property] != row[column.property]) {
        return "background-color: rgb(144 199 255);"
      }
    },

效果展示

表格中有两种类型的可编辑单元格,一种是输入框,一种是下拉框。当鼠标移入一个可编辑的单元格时,它会显示一个编辑图标,提示可以点击编辑。当点击一个可编辑的单元格时,它会显示一个输入框或者下拉框修改数据。当修改完数据后,按下回车键或者点击其他地方,它会保存数据,并且切换回文本显示。同时可以看到,修改过的单元格会有一个蓝色的背景色,清楚地看到数据的变化。还可以点击右侧的删除按钮,删除一行数据。代码如下:

cellstyle({ row, column, rowIndex, columnIndex }) {
      if (this.tableDataCopy[rowIndex][column.property] != row[column.property]) {
        return "background-color: rgb(144 199 255);"
      }
    },

Vue.js实现可编辑表格并高亮修改的单元格_第2张图片
Vue.js实现可编辑表格并高亮修改的单元格_第3张图片

.el-input__icon {
  line-height: 24px !important;
}

.el-button--text {
  height: 24px;

}

.item {
  .el-input--suffix .el-input__inner {
    padding-right: 20px;
    padding-left: 10px;
  }

  .el-input__inner {
    height: 24px !important;
    white-space: nowrap;
    text-overflow: ellipsis;
    overflow: hidden;
  }

  .item__input {
    display: none;
  }

  .item__txt {
    box-sizing: border-box;
    border: 1px solid transparent;
    width: 100px;
    line-height: 24px;
    padding: 0 8px;
    white-space: nowrap;
    text-overflow: ellipsis;
    overflow: hidden;
  }

  .item__txt--hover {
    border: 1px solid #dddddd;
    border-radius: 4px;
    cursor: text;
  }
}
.el-table {
  .el-table__cell {
    padding: 6px 0 !important;
  }

}

你可能感兴趣的:(vue,vue.js,elementui)