Vxe-Table实现实时编辑、保存功能

3,498 阅读1分钟
   今天,老总接了个单,需要做成实时标记、保存的项目。还要保持公司内部开发规范。
瞬间,不想做了。(公司内部采用的是ElementUi)需要开发的再次开发的点太多了。突然,技术总监说:“可以用别的框架,样式靠近饿了吗就行。”。心想:嗯这样可以多多摸鱼了。

思路

1、聚焦(点击)触发编辑
2、失焦触发保存

战前动员(准备)

VxeTable
ElementUi

1、安装Vxe-Table

npm install xe-utils vxe-table@legacy

2、Vue注册

import Vue from 'vue'
import VXETable from 'vxe-table'
import 'vxe-table/lib/style.css'

Vue.use(VXETable)

3、引入ElementUI

1、安装插件

npm install xe-utils vxe-table@3 vxe-table-plugin-element@1 element-ui

2、Vue注册

// ...
import VXETable from 'vxe-table'
import VXETablePluginElement from 'vxe-table-plugin-element'
import 'vxe-table-plugin-element/dist/style.css'
// ...

VXETable.use(VXETablePluginElement)

4、项目UI

1662623851563.png

5、源码

<template>
  <div>
    <p>Table 演示</p>
    <vxe-toolbar>
      <template #buttons>
        <vxe-button icon="vxe-icon-add" status="success" @click="addRow('bottom')">新增</vxe-button>
        <vxe-button icon="vxe-icon-add" status="success" @click="addRow('top')">插入</vxe-button>
        <vxe-button icon="vxe-icon-close" status="danger" @click="deleteRow">删除</vxe-button>
        <vxe-button icon="vxe-icon-check" :disabled="realTime" status="warning" @click="saveRow">保存</vxe-button>
      </template>
      <template #tools>
        实时保存:
        <vxe-radio-group v-model="realTime">
          <vxe-radio-button :label="true" content="是"></vxe-radio-button>
          <vxe-radio-button :label="false" content="否"></vxe-radio-button>
        </vxe-radio-group>
      </template>
    </vxe-toolbar>
    <vxe-table
      border
      keep-source
      ref="xTable"
      :data="tableData"
      :tree-config="treeConfig"
      :edit-config="editConfig"
      @edit-closed="editClosedEvent"
    >
      <vxe-column type="checkbox" width="60"></vxe-column>
      <vxe-column field="id" title="ID" min-width="50" tree-node />
      <vxe-column field="pid" title="PID" min-width="50" />
      <vxe-column
        field="name"
        title="NAME"
        min-width="200"
        :edit-render="{ autofocus: '.vxe-input--inner' }"
      >
        <template #edit="scope">
          <vxe-input v-model="scope.row.name" type="text"></vxe-input>
        </template>
      </vxe-column>
      <vxe-column field="sex" title="SEX" min-width="60"></vxe-column>
      <vxe-column field="date" title="DATE" min-width="140"></vxe-column>
      <vxe-column field="address" title="ADDRESS" min-width="300"></vxe-column>
    </vxe-table>
  </div>
</template>

<script>
import XEUtils from "xe-utils";

export default {
  name: "VXETable",
  data() {
    return {
      tableData: [
        {
          id: 1,
          pid: null,
          name: "test1",
          sex: "Man",
          date: "2019-05-01",
          address: "address abc 1"
        },
        {
          id: 2,
          pid: null,
          name: "test2",
          sex: "Man",
          date: "2019-05-01",
          address: "address abc 2"
        },
        {
          id: 3,
          pid: null,
          name: "test3",
          sex: "Man",
          date: "2019-05-01",
          address: "address abc 3"
        },
        {
          id: 4,
          pid: 1,
          name: "test1.1",
          sex: "Man",
          date: "2019-05-01",
          address: "address abc 4"
        },
        {
          id: 5,
          pid: 1,
          name: "test1.2",
          sex: "Man",
          date: "2019-05-01",
          address: "address abc 5"
        }
      ],
      editConfig: { trigger: "click", mode: "cell", showStatus: true },
      treeConfig: {
        transform: true,
        rowField: "id",
        parentField: "pid",
        lazy: false
      },
      realTime: false
    };
  },
  mounted() {
    this.$nextTick(() => {
      this.$refs.xTable.setAllTreeExpand(true);
    });
  },
  methods: {
    /** 新增/插入 */
    addRow(local) {
      const $table = this.$refs.xTable;
      const { tableData } = $table.getTableData();
      const seq = tableData.length + 1;
      let location = -1;
      let parentRow = null;
      let checkedIndex = -1;
      let index = 0;

      if (local === "bottom") {
        index += 1;
      } else if (local === "top") {
        location = 0;
      }

      const checkedRow = $table.getCheckboxRecords();
      if (checkedRow.length > 1) {
        alert("请选择单行新增!");
        return;
      }
      if (checkedRow.length > 0) {
        checkedIndex = tableData.findIndex(
          e => e._X_ROW_KEY == checkedRow[0]._X_ROW_KEY
        );
        if (checkedIndex > -1) {
          location = tableData[checkedIndex + index];
          parentRow = $table.getParentRow(tableData[checkedIndex]);
          if (parentRow) {
            location = -1;
          }
        }
      }

      let newRecord = {
        id: seq,
        name: "新数据",
        date: XEUtils.toDateString(new Date(), "yyyy-MM-dd"),
        address: "address abc " + seq,
        pid: parentRow ? parentRow.id : null
      };

      $table.insertAt(newRecord, location).then(({ row }) => {
        $table.setActiveRow(row);
      });
    },
    /** 删除 */
    deleteRow() {
      const $table = this.$refs.xTable;
      const checkedRow = $table.getCheckboxRecords();
      if (checkedRow.length > 0) {
        $table.remove(checkedRow);
      }
    },
    /** 保存 */
    saveRow() {
      const $table = this.$refs.xTable;
      console.log($table.getRecordset());
    },
    /** 表格编辑关闭 */
    editClosedEvent({ row }) {
      if (!this.realTime) {
        return;
      }
      const $table = this.$refs.xTable;
      const parentRow = $table.getParentRow(row);

      // 表格修改过
      if ($table.isUpdateByRow(row)) {
        // 存在父项
        if (parentRow) {
          return setTimeout(() => {
            $table.reloadRow(parentRow);
          }, 3000);
        }
        // 三秒后清除表格状态
        setTimeout(() => {
          $table.reloadRow(row);
        }, 3000);
      }
    }
  }
};
</script>