iview的table动态合并行列的完整示例

官网解析

先看看官网示例

<template>
  <Table
    :columns="columns"
    :data="data"
    border
    :span-method="handleSpan"
  ></Table>
</template>
<script>
export default {
  data() {
    return {
      columns: [
        {
          title: "Date",
          key: "date",
        },
        {
          title: "Name",
          key: "name",
        },
        {
          title: "Age",
          key: "age",
        },
        {
          title: "Address",
          key: "address",
        },
      ],
      data: [
        {
          name: "John Brown",
          age: 18,
          address: "New York No. 1 Lake Park",
          date: "2016-10-03",
        },
        {
          name: "Jim Green",
          age: 24,
          address: "London No. 1 Lake Park",
          date: "2016-10-01",
        },
        {
          name: "Joe Black",
          age: 30,
          address: "Sydney No. 1 Lake Park",
          date: "2016-10-02",
        },
        {
          name: "Jon Snow",
          age: 26,
          address: "Ottawa No. 2 Lake Park",
          date: "2016-10-04",
        },
      ],
    };
  },
  methods: {
    handleSpan({ row, column, rowIndex, columnIndex }) {
      if (rowIndex === 0 && columnIndex === 0) { // 表示的是第一行第一列
        return [1, 2]; // 表示合并1行2列
      } else if (rowIndex === 0 && columnIndex === 1) { // 表示的是第一行第二列
        return [0, 0]; // 表示合并0行0列,即被合并的单元格(注意:被合并到单元格一定要返回[0,0]否则数据会乱套)
      }
      if (rowIndex === 2 && columnIndex === 0) { // 表示的是第三行第一列
        return { // 表示合并2行1列
          rowspan: 2,
          colspan: 1,
        };
      } else if (rowIndex === 3 && columnIndex === 0) { // 表示的是第四行第一列
        return { // 表示合并0行0列
          rowspan: 0,
          colspan: 0,
        };
      }
    },
  },
};
</script>

iview的table动态合并行列的完整示例_第1张图片
主要是设置 span-method属性可以指定合并行或列的算法。
上面代码示例是根据行号和列号来进行合并判断的,现实情况我们很有可能需要动态判断合并的单元格。

注意:在合并行时,需要合并到数据必须相邻,数据在数组中的下标要紧挨这,否则无法合并。可以自己根据需要将数据排好序后再合并。

示例1:只根据某一列合并行

假设我们根据name值相同的合并单元格
效果图:
iview的table动态合并行列的完整示例_第2张图片
代码实现:

<template>
  <Table
    :columns="columns"
    :data="data"
    border
    :span-method="handleSpan"
  ></Table>
</template>
<script>
export default {
  data() {
    return {
      columns: [
        {
          title: "Date",
          key: "date",
        },
        {
          title: "Name",
          key: "name",
        },
        {
          title: "Age",
          key: "age",
        },
        {
          title: "Address",
          key: "address",
        },
      ],
      resData: [
        {
          id: "1",
          name: "John Brown",
          age: 18,
          address: "New York No. 1 Lake Park",
          date: "2016-10-03",
        },
        {
          id: "3",
          name: "John Brown",
          age: 24,
          address: "London No. 1 Lake Park",
          date: "2016-10-01",
        },
        {
          id: "2",
          name: "Joe Black",
          age: 30,
          address: "Sydney No. 1 Lake Park",
          date: "2016-10-02",
        },
        {
          id: "4",
          name: "Jon Snow",
          age: 26,
          address: "Ottawa No. 2 Lake Park",
          date: "2016-10-04",
        },
      ],
      data: [],
    };
  },
  methods: {
    handleSpan({ row, column, rowIndex, columnIndex }) {
      //合并第二列,这里columnIndex===1 根据具体业务来,比如本示例中需要合并的name为第二列
      if (columnIndex === 1) {
        //计算合并的行数列数
        let x = row.mergeCol === 0 ? 0 : row.mergeCol;
        let y = row.mergeCol === 0 ? 0 : 1;
        return [x, y];
      }
    },
    formatData(data) {
      let names = [];
      //筛选出不重复的 name值,将其放到 names数组中
      data.forEach((e) => {
        if (!names.includes(e.name)) {
          names.push(e.name);
        }
      });

      let nameNums = [];
      //将names数组中的 name值设置默认合并0个单元格,放到 nameNums中
      names.forEach((e) => {
        nameNums.push({ name: e, num: 0 });
      });

      //计算每种 name值所在行需要合并的单元格数
      data.forEach((e) => {
        nameNums.forEach((n) => {
          if (e.name === n.name) {
            n.num++;
          }
        });
      });

      //将计算后的合并单元格数整合到 data中
      data.forEach((e) => {
        nameNums.forEach((n) => {
          if (e.name === n.name) {
            if (names.includes(e.name)) {
              e.mergeCol = n.num;
              //删除已经设置过的值(防止被合并的单元格进到这个 if 语句中)
              names.splice(names.indexOf(n.name), 1);
            } else {
              //被合并的单元格设置为 0
              e.mergeCol = 0;
            }
          }
        });
      });

      //将整理后的数据交给表格渲染
      return data;
    },
  },
  mounted() {
    this.data = this.formatData(this.resData);
  },
};
</script>

示例2:先根据某一列合并行,再根据合并的行合并另一列中的行

什么意思,意思就是比如我先合并了name列中相同的行,如果name列已经合并的行中还有相同的age列需要合并的话,应该怎么做?

数据预处理:先排序,把相同的name值放到一起,然后再把相同的age放到一起

效果图:
iview的table动态合并行列的完整示例_第3张图片
代码实现:

<template>
  <Table
    class="border-table"
    :columns="columns"
    :data="data"
    border
    :span-method="handleSpan"
  ></Table>
</template>
<script>
export default {
  data() {
    return {
      columns: [
        {
          title: "Date",
          key: "date",
        },
        {
          title: "Name",
          key: "name",
        },
        {
          title: "Age",
          key: "age",
        },
        {
          title: "Address",
          key: "address",
        },
      ],
      resData: [
        {
          id: "1",
          name: "John Brown",
          age: 18,
          address: "New York No. 1 Lake Park",
          date: "2016-10-03",
        },
        {
          id: "3",
          name: "John Brown",
          age: 24,
          address: "London No. 1 Lake Park",
          date: "2016-10-01",
        },
        {
          id: "5",
          name: "John Brown",
          age: 24,
          address: "London No. 2 Lake Park",
          date: "2016-10-03",
        },
        {
          id: "2",
          name: "Joe Black",
          age: 30,
          address: "Sydney No. 1 Lake Park",
          date: "2016-10-02",
        },
        {
          id: "4",
          name: "Jon Snow",
          age: 26,
          address: "Ottawa No. 2 Lake Park",
          date: "2016-10-04",
        },
      ],
      data: [],
    };
  },
  methods: {
    handleSpan({ row, column, rowIndex, columnIndex }) {
      //合并第二列,这里columnIndex===1 根据具体业务来,比如本示例中需要合并的name为第二列
      if (columnIndex === 1) {
        //计算合并的行数列数
        let x = row.mergeCol === 0 ? 0 : row.mergeCol;
        let y = row.mergeCol === 0 ? 0 : 1;
        return [x, y];
      }
      // age 合并
      if (columnIndex === 2) {
        //计算合并的行数列数
        let x = row.mergeColAge === 0 ? 0 : row.mergeColAge;
        let y = row.mergeColAge === 0 ? 0 : 1;
        return [x, y];
      }
    },
    formatData(data) {
      // 根据 name 排序 age
      for (let i = 0; i < data.length - 1; i++) {
        for (let n = i + 1; n < data.length; n++) {
          if (data[i].age > data[n].age) {
            [data[i], data[n]] = [data[n], data[i]];
          }
        }
      }
      let names = [];
      //筛选出不重复的 name值,将其放到 names数组中
      data.forEach((e) => {
        if (!names.includes(e.name)) {
          names.push(e.name);
        }
      });

      let nameNums = [];
      //将names数组中的 name值设置默认合并0个单元格,放到 nameNums中
      names.forEach((e) => {
        nameNums.push({ name: e, num: 0 });
      });

      //计算每种 name值所在行需要合并的单元格数
      data.forEach((e) => {
        nameNums.forEach((n) => {
          if (e.name === n.name) {
            n.num++;
          }
        });
      });

      //将计算后的合并单元格数整合到 data中
      data.forEach((e) => {
        nameNums.forEach((n) => {
          if (e.name === n.name) {
            if (names.includes(e.name)) {
              e.mergeCol = n.num;
              //删除已经设置过的值(防止被合并的单元格进到这个 if 语句中)
              names.splice(names.indexOf(n.name), 1);
            } else {
              //被合并的单元格设置为 0
              e.mergeCol = 0;
            }
          }
        });
      });

      //不唯一且重复的情况下,在唯一的基础上合并重复
      for (let j = 0; j < data.length; j++) {
        //  > 1 name 表示 有合并需要在name合并的row中 再合并
        if (data[j].mergeCol > 1) {
          for (let k = 0; k < data[j].mergeCol; k++) {
            //age合并
            if (data[j + k].ageAlready !== 1) { // 需要这个条件,避免数据重复
              if (k + 1 < data[j].mergeCol) {
                data[j + k].mergeColAge = 1
                for (let b = k + 1; b < data[j].mergeCol; b++) {
                  if (data[j + k].age === data[j + b].age) {
                    data[j + k].mergeColAge++;
                    data[j + b].mergeColAge = 0;
                    data[j + b].ageAlready = 1;
                  } else {
                    break;
                  }
                }
              }
            }
          }
        }
        // 如果有需要在age合并到row中 再合并的话代码添加到此处
      }

      //将整理后的数据交给表格渲染
      return data;
    },
  },
  mounted() {
    this.data = this.formatData(this.resData);
  },
};
</script>

你可能感兴趣的:(vue,javascript,前端,vue.js,iview)