表格数据对比

608 阅读1分钟

根据项目需求,实现表格数据不同显示红色背景,数据新增显示绿色背景 主要是采用唯一的id去比对,for循环缓存到map里面然后对比,不同的就存进去,不用每一个数组都push,在computed里面实现。

DiffTable.vue

<template>
  <div class="diff-table-container">
    <el-table v-for="(data, i) in completedData" :key="i" :data="data" :row-style="markRowStyles" :cell-style="markCellStyles" border>
      <el-table-column v-for="item in columns" :key="`${i}${item.prop}`" v-bind="item" align="center" />
    </el-table>
  </div>
</template>

<script>
function deepClone (val) {
  // 看需求要不要做深拷贝
  return val;
}

export default {
  name: "DiffTable",
  props: {
    uniqueKey: {
      type: String,
      default: "id"
    },
    dataGroup: {
      type: Array,
      validator: val => val.length === 2
    },
    columns: {
      type: Array,
      required: true
    }
  },
  data () {
    return {
      DIFF_CELL_KEY: Symbol("diffCells"),
      COMPLETED_KEY: Symbol("completed")
    };
  },
  computed: {
    // 处理完成的数据
    completedData ({ dataGroup, uniqueKey, columns, DIFF_CELL_KEY, COMPLETED_KEY }) {
      // 这一步不是必要的,根据业务需求来,如果规定不能修改原数据的话就做一下深拷贝
      const _dataGroup = deepClone(dataGroup);
      // Map<string|number, object>,ts不太熟,应该是这么写,其实就是row[unique]: row
      const cacheMap = new Map();
      // 先遍历一次第一组数据,初始化DIFF_CELL_KEY数组,然后存进map中
      for (const _row of _dataGroup[0]) {
        _row[DIFF_CELL_KEY] = [];
        cacheMap.set(_row[uniqueKey], _row);
      }
      console.log(cacheMap, 'row')
      // 遍历第二组数据,里面还有一次循环,因为只处理columns里面定义的属性,其他属性不做对比
      for (const _row of _dataGroup[1]) {
        for (const { prop } of columns) {
          // 如果是唯一key就直接跳过
          if (prop === uniqueKey) continue;
          // 从缓存中查找相同的一条数据
          const original = cacheMap.get(_row[uniqueKey]);
          // 如果找不到就说明这条数据是新增的,直接跳过
          if (!original) continue;
          // 否则就在两组数据中打一个标识表示已处理过,不是新增的
          _row[COMPLETED_KEY] = true;
          original[COMPLETED_KEY] = true;
          // 最后对比两个属性值,如果相同就push进DIFF_CELL_KEY数组中
          // 注意这里DIFF_CELL_KEY数组只存在于第一组数据当中
          // 因为只要有差异就会在所有表格中显示,所以不用每一组数据都存
          _row[prop] !== original[prop] && original[DIFF_CELL_KEY].push(prop);
        }
      }
      // 将map存一份到this中,因为会在处理样式的时候用到
      this.$_cacheMap = cacheMap;
      return _dataGroup;
    }
  },
  methods: {
    markRowStyles ({ row }) {
      return (
        !row[this.COMPLETED_KEY] && {
          backgroundColor: "#E1F3D8"
        }
      );
    },
    markCellStyles ({ row, column }) {
      const { $_cacheMap, uniqueKey, DIFF_CELL_KEY } = this;
      const _cacheRow = $_cacheMap.get(row[uniqueKey]);
      return (
        _cacheRow &&
        _cacheRow[DIFF_CELL_KEY].includes(column.property) && {
          backgroundColor: "#FDE2E2"
        }
      );
    }
  }
};
</script>

<style scoped>
.diff-table-container {
  display: flex;
  align-items: flex-start;
}
.el-table + .el-table {
  margin-left: 20px;
}
</style>

index.vue

<template>
  <div class="Tabel_Data">
    <diff-table :data-group="[oldData, newData]" :columns="tableColumns" />
  </div>
</template>
 
<script>
import DiffTable from "./DiffTable";

export default {
  name: "Index",
  components: {
    DiffTable
  },
  data () {
    return {
      oldData: [
        { id: 1, name: "zhangsan1", age: 23, address: "zxczxczxc", add: '0000' },
        { id: 2, name: "zhangsan2", age: 23.5, address: "zxczxczxc", add: '0000' },
        { id: 3, name: "zhangsan34", age: 23, address: "zxczxczxc", add: '0000' },
        { id: 4, name: "zhangsan4", age: 23, address: "zxczxczxc", add: '0000' },
        { id: 5, name: "zhangsan5", age: 23, address: "zxczxczxc", add: '0000' },
        { id: 6, name: "zhangsan5", age: 23, address: "zxczxczxc", add: '0000' }
      ],
      newData: [
        { id: 1, name: "zhangsan1", age: 23, address: "zxczxczxc", add: '0000' },
        { id: 2, name: "zhangsan2", age: 23, address: "zxczxczxc", add: '0000' },
        { id: 4, name: "zhangsan4", age: 23, address: "地址地址地址", add: '00010' },
        { id: 3, name: "zhangsan3", age: 23, address: "zxczxczxc", add: '0000' },
        { id: 5, name: "zhangsan5", age: 23, address: "zxczxczxc", add: '0000' },
        { id: 7, name: "zhangsan5", age: 23, address: "zxczxczxc", add: '0000' },
        { id: 8, name: "zhangsan5", age: 23, address: "zxczxczxc", add: '0000' }
      ],
      tableColumns: [
        { label: "id", prop: "id" },
        { label: "名称", prop: "name" },
        { label: "年龄", prop: "age" },
        { label: "地址", prop: "address" },
        { label: "地址1", prop: "add" },
      ]
    };
  }
};
</script>

最终的效果

image.png