欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

利用vue對(duì)比兩組數(shù)據(jù)差異的可視化組件詳解

 更新時(shí)間:2021年09月30日 10:24:20   作者:小周小周萬事無憂  
這篇文章主要給大家介紹了關(guān)于利用vue對(duì)比兩組數(shù)據(jù)差異的可視化組件的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用vue具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下

如題,朋友有個(gè)這樣的需求,感覺挺常見,發(fā)出來給大家參考一下

需求:

用el-table展示兩組數(shù)據(jù),有差異的單元格顯示紅色,新增的顯示整行綠色

大概要點(diǎn):

  • 需要一個(gè)數(shù)據(jù)組,里面包含兩組需要對(duì)比的數(shù)據(jù)
  • 需要一個(gè)唯一的key,用來確定某一行的數(shù)據(jù)是否在其他數(shù)據(jù)中存在(是否是新增
  • 接受一個(gè)表格列的配置,用于渲染表格,同時(shí)對(duì)比差異只按照配置的數(shù)據(jù)來,其他的數(shù)據(jù)無需進(jìn)行對(duì)比

根據(jù)剛才的要點(diǎn)可以建立一下組件的props:

props: {
  uniqueKey: {
    type: String,
    default: "id"
  },
  dataGroup: {
    type: Array,
    validator: val => val.length === 2
  },
  columns: {
    type: Array,
    required: true
  }
}

唯一id默認(rèn)為id;columns的格式就按照el-table-column的來,定義為{ label, prop, ... }

組件的基本樣式也很簡單:

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

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

如上所示,就是把兩個(gè)表格簡單的橫向排布。這里的completedData指進(jìn)行diff處理完成之后的數(shù)據(jù),格式和傳進(jìn)來的dataGroup是一樣的。markRowStyles和markRowStyles都是el-table提供的,分別指行和列的樣式,值為對(duì)象或返回一個(gè)對(duì)象的函數(shù)。

接下來定義兩個(gè)Symbol,之后在diff數(shù)據(jù)的時(shí)候會(huì)給數(shù)據(jù)加上標(biāo)記,用Symbol做標(biāo)記可以防止屬性名沖突。

data() {
  return {
    DIFF_CELL_KEY: Symbol("diffCells"), // 一個(gè)數(shù)組,存儲(chǔ)有差異的cell屬性名
    COMPLETED_KEY: Symbol("completed") // 標(biāo)記已完成處理
  };
}

然后diff的樣式處理也可以直接定下來了。

methods: {
  // 完成處理之后沒有標(biāo)記的,就表示只在一組數(shù)據(jù)中出現(xiàn),也就是新增數(shù)據(jù)
  markRowStyles({ row }) {
    return (
      !row[this.COMPLETED_KEY] && {
        backgroundColor: "#E1F3D8"
      }
    );
  },
  // 根據(jù)當(dāng)前行的唯一key,找到map中緩存的行數(shù)據(jù)
  // 就是dataGroup[0].find(item => item[uniqueKey] === row[uniqueKey])
  // 然后判斷DIFF_CELL_KEY數(shù)組中是否包含當(dāng)前列的屬性名
  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"
      }
    );
  }
}

最后就是diff的處理了,直接用計(jì)算屬性去做,處理完成之后返回新數(shù)據(jù):

computed: {
  // 處理完成的數(shù)據(jù)
  completedData({ dataGroup, uniqueKey, columns, DIFF_CELL_KEY, COMPLETED_KEY }) {
    // 這一步不是必要的,根據(jù)業(yè)務(wù)需求來,如果規(guī)定不能修改原數(shù)據(jù)的話就做一下深拷貝
    const _dataGroup = deepClone(dataGroup);
    // Map<string|number, object>,ts不太熟,應(yīng)該是這么寫,其實(shí)就是row[unique]: row
    const cacheMap = new Map();
    // 先遍歷一次第一組數(shù)據(jù),初始化DIFF_CELL_KEY數(shù)組,然后存進(jìn)map中
    for (const _row of _dataGroup[0]) {
      _row[DIFF_CELL_KEY] = [];
      cacheMap.set(_row[uniqueKey], _row);
    }
    // 遍歷第二組數(shù)據(jù),里面還有一次循環(huán),因?yàn)橹惶幚韈olumns里面定義的屬性,其他屬性不做對(duì)比
    for (const _row of _dataGroup[1]) {
      for (const { prop } of columns) {
        // 如果是唯一key就直接跳過
        if (prop === uniqueKey) continue;
        // 從緩存中查找相同的一條數(shù)據(jù)
        const original = cacheMap.get(_row[uniqueKey]);
        // 如果找不到就說明這條數(shù)據(jù)是新增的,直接跳過
        if (!original) continue;
        // 否則就在兩組數(shù)據(jù)中打一個(gè)標(biāo)識(shí)表示已處理過,不是新增的
        _row[COMPLETED_KEY] = true;
        original[COMPLETED_KEY] = true;
        // 最后對(duì)比兩個(gè)屬性值,如果相同就push進(jìn)DIFF_CELL_KEY數(shù)組中
        // 注意這里DIFF_CELL_KEY數(shù)組只存在于第一組數(shù)據(jù)當(dāng)中
        // 因?yàn)橹灰胁町惥蜁?huì)在所有表格中顯示,所以不用每一組數(shù)據(jù)都存
        _row[prop] !== original[prop] && original[DIFF_CELL_KEY].push(prop);
      }
    }
    // 將map存一份到this中,因?yàn)闀?huì)在處理樣式的時(shí)候用到
    this.$_cacheMap = cacheMap;
    return _dataGroup;
  }
}

完事了,最后貼一下完整代碼:

<template>
  <div class="diff-table-container">
    <el-table
      v-for="(data, i) in completedData"
      :key="i"
      :data="data"
      :row-style="markRowStyles"
      :cell-style="markCellStyles"
    >
      <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);
      const cacheMap = new Map();
      for (const _row of _dataGroup[0]) {
        _row[DIFF_CELL_KEY] = [];
        cacheMap.set(_row[uniqueKey], _row);
      }
      for (const _row of _dataGroup[1]) {
        for (const { prop } of columns) {
          if (prop === uniqueKey) continue;
          const original = cacheMap.get(_row[uniqueKey]);
          if (!original) continue;
          _row[COMPLETED_KEY] = true;
          original[COMPLETED_KEY] = true;
          _row[prop] !== original[prop] && original[DIFF_CELL_KEY].push(prop);
        }
      }
      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 lang="scss" scoped>
.diff-table-container {
  display: flex;
  align-items: flex-start;
  .el-table + .el-table {
    margin-left: 20px;
  }
}
</style>

使用示例:

<template>
  <diff-table :data-group="[oldData, newData]" :columns="tableColumns" />
</template>

<script>
import DiffTable from "./DiffTable.vue";

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

效果預(yù)覽:

擴(kuò)展功能TODO:

  • 可配置n組數(shù)據(jù)進(jìn)行對(duì)比
  • 數(shù)據(jù)超過兩組之后應(yīng)該新增DELETE_ROW_KEY標(biāo)記一條刪除的數(shù)據(jù)
    • 邏輯大概為:只存在于一組數(shù)據(jù)中的為新增;存在多組數(shù)據(jù)中但不是所有數(shù)據(jù)的,不包含的數(shù)據(jù)組內(nèi)就要標(biāo)記為刪除的數(shù)據(jù)
  • 可配置diff樣式、自定義diff規(guī)則等

總結(jié)

到此這篇關(guān)于利用vue對(duì)比兩組數(shù)據(jù)差異的可視化組件的文章就介紹到這了,更多相關(guān)vue對(duì)比兩組數(shù)據(jù)差異內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 解決vue.js中settimeout遇到的問題(時(shí)間參數(shù)短效果不穩(wěn)定)

    解決vue.js中settimeout遇到的問題(時(shí)間參數(shù)短效果不穩(wěn)定)

    這篇文章主要介紹了解決vue.js中settimeout遇到的問題(時(shí)間參數(shù)短效果不穩(wěn)定),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-07-07
  • vue3實(shí)現(xiàn)密碼輸入框效果的示例代碼

    vue3實(shí)現(xiàn)密碼輸入框效果的示例代碼

    這篇文章主要為大家詳細(xì)介紹了如何利用vue3實(shí)現(xiàn)6位的密碼輸入框效果,文中的示例代碼簡潔易懂,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-08-08
  • 淺談vue單頁面中有多個(gè)echarts圖表時(shí)的公用代碼寫法

    淺談vue單頁面中有多個(gè)echarts圖表時(shí)的公用代碼寫法

    這篇文章主要介紹了淺談vue單頁面中有多個(gè)echarts圖表時(shí)的公用代碼寫法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-07-07
  • 關(guān)于vue中媒體查詢不起效的原因總結(jié)

    關(guān)于vue中媒體查詢不起效的原因總結(jié)

    這篇文章主要介紹了關(guān)于vue中媒體查詢不起效的原因總結(jié),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-09-09
  • 如何本地運(yùn)行vue?dist文件

    如何本地運(yùn)行vue?dist文件

    這篇文章主要介紹了如何本地運(yùn)行vue?dist文件,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-05-05
  • Vue中的@blur/@focus事件解讀

    Vue中的@blur/@focus事件解讀

    這篇文章主要介紹了Vue中的@blur/@focus事件解讀,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • Vue3中的provide、inject 的用法

    Vue3中的provide、inject 的用法

    這篇文章主要介紹了Vue3中的provide、inject 的用法,需要的朋友可以參考下
    2023-03-03
  • axios異步提交表單數(shù)據(jù)的幾種方法

    axios異步提交表單數(shù)據(jù)的幾種方法

    這篇文章主要給大家介紹了關(guān)于axios異步提交表單數(shù)據(jù)的幾種方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)各位大家學(xué)習(xí)或者使用axios具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • Vue.js彈出模態(tài)框組件開發(fā)的示例代碼

    Vue.js彈出模態(tài)框組件開發(fā)的示例代碼

    本篇文章主要介紹了Vue.js彈出模態(tài)框組件開發(fā)的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-07-07
  • vue.js語法及常用指令

    vue.js語法及常用指令

    vue.js相比于Angular.js,Vue.js提供了更加簡潔、更易于理解的API,使得我們能夠快速地上手并使用Vue.js。下面通過本文給大家分享vue.js語法及常用指令,希望對(duì)大家有所幫助
    2017-10-10

最新評(píng)論