vue,js 合并单元格行和列,数组格式处理

wenlong_15 2021-03-28 09:45:28

<template>
<div>
<table width="100%" cellspan="0">
<tr v-for="(itemTr, indexTr) in tableData" :key="indexTr">
<td :rowspan="itemTd.rowspan" :colspan="itemTd.colspan" v-for="(itemTd, indexTd) in itemTr" :key="indexTd">{{ itemTd.name }}</td>
</tr>
</table>
</div>
</template>

<script>
export default {
name: "HelloWorld",
data() {
return {
tableData: [
["周一", "周一", "周一", "周四", "周五", "周六"],
["语文", "数学", "英语", "历史", "物理", "化学"],
["语文", "英语", "数学", "物理", "历史", "体育"],
["语文", "英语", "物理", "数学", "体育", "历史"],
["数学", "语文", "化学", "物理", "历史", "体育"],
["数学", "语文", "化学", "物理", "体育", "历史"],
]
};
},

created() {
this.tableData = this.rowspanData(this.tableData)
},

methods: {
//合并行
rowspanData(data) {
let rowspanData = []
first: for (let i = 0; i < data.length; i++) {
let rowsArray = [] //一行
second: for (let j = 0; j < data[i].length; j++) {
//一列
let obj = {
name: data[i][j],
rowspan: 1, //行
colspan: 1 //列
}
if (i === 0) {
rowsArray.push(obj)
}
if (i > 0) {
if (data[i][j] === data[i - 1][j]) {
//?只取了一次值
console.log(data[i][j]);
console.log(data[i - 1][j]);
rowspanData[i - 1][j].rowspan++
} else {
rowsArray.push(obj)
}
}
}
rowspanData.push(rowsArray)
}
//console.log(rowspanData);
return rowspanData
},

//合并列
colspanData(data) {
let colspanData = []
first: for (let i = 0; i < data.length; i++) {
let rowsArray = [] //一行
second: for (let j = 0; j < data[i].length; j++) {
//一列
let obj = {
name: data[i][j],
colspan: 1, //列
rowspan: 1 //行
}
if (rowsArray.length > 0) {
colspanData: for (let k = 0; k < rowsArray.length; k++) {
if (data[i][j] === rowsArray[k].name) {
rowsArray[k].colspan++;
continue second
}
}
}
rowsArray.push(obj)
}
colspanData.push(rowsArray)
}
return colspanData
}
}
};
</script>
<style scoped>
table {
border: 1px solid #666;
}

table td {
border-bottom: 1px solid #666;
border-right: 1px solid #666;
}
</style>


上面是vue的代码,想把数组处理成 下面的数组格式,下面的数据只是举例,

tableData: [{
                            name: "周一",
                            colspan: 3, //列
                            rowspan: 1 //行
                        },

{
                            name: "语文",
                            colspan: 1, //列
                            rowspan: 3 //行
                        }


]


最后的数据可以用vue的v-for循环出来,请大家帮忙看看。

<table width="100%" cellspan="0">
<tr v-for="(itemTr, indexTr) in tableData" :key="indexTr">
<td :rowspan="itemTd.rowspan" :colspan="itemTd.colspan" v-for="(itemTd, indexTd) in itemTr" :key="indexTd">{{ itemTd.name }}</td>
</tr>
</table>


...全文
628 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
wenlong_15 2021-03-31
  • 打赏
  • 举报
回复
引用 9 楼 泡泡鱼_ 的回复:
[quote=引用 8 楼 wenlong_15 的回复:][quote=引用 5 楼 泡泡鱼_ 的回复:]trIndex应该是换成tdIndex才对,也更好理解
如果行和列数据有相同的会有问题,这样的不好解决吧?[/quote] 至少不能靠合并去解决,table解决不了的。 你可以尝试使用样式去解决,达到一个相对的解决 我示例中是优先合并列,在合并行的时候,是主动排除了已经合并过的列的,你需要将条件去除后,然后再针对是否有合并过列做不同的,合并过的,则将name='$$$'//这里面的$$$是一个固定的;未合并过的,还是按原先的处理 然后模板中: 控制内容输出:{{td.name=='$$$'? '' : td.name}} 然后就是解决样式了,你可以给单元格设定样式,关键在于边框样式,比如,你可以设置当td.name=='$$$'时,下边框为0。这样,可以达到一个视觉上的合并[/quote]
            ["","","","","可见光(%)","可见光(%)","太阳能(%)","太阳能(%)","玻璃遮阳系数SC"],
            ["玻璃","玻璃","玻璃","玻璃颜色","透射","反射","透射","反射","玻璃遮阳系数SC"],
            ["中空玻璃","间隔层6mm","间隔层6mm","无色",79,14,63,12,0.81],
            ["中空玻璃","间隔层12mm","间隔层12mm","无色",75,14,58,11,0.77],
            ["着色中空玻璃","","","蓝色",66,12,47,8.4,0.65],
            ["着色中空玻璃","","","绿色",65,12,48,8.5,0.66],
            ["着色中空玻璃","","","茶色",46,10,46,8.6,0.64],
            ["着色中空玻璃","","","灰色",39,8,38,8,0.54],
            ["热反射中空玻璃","反射颜色","深绿色","无色",8,16,12,11,0.26],
            ["热反射中空玻璃","反射颜色","绿色","绿色",45,9,26,6,0.42],
            ["热反射中空玻璃","反射颜色","绿色","蓝绿",40,9,24,6,0.40],
            ["热反射中空玻璃","反射颜色","蓝绿色","蓝绿",49,26,31,14,0.46],
            ["热反射中空玻璃","反射颜色","灰绿色","绿色",46,17,28,9,0.44],
            ["热反射中空玻璃","反射颜色","灰绿色","蓝绿",40,19,28,11,0.44],
            ["热反射中空玻璃","反射颜色","现代绿色","绿色",48,26,28,13,0.44],
            ["热反射中空玻璃","反射颜色","蓝色","无色",41,17,33,13,0.48],
            ["热反射中空玻璃","反射颜色","银灰色","无色",48,27,53,21,0.69],
            ["辐射率≤0.25Low-E中空玻璃(在线)","","","无色",63,16,48,13,0.63],
            ["辐射率≤0.25Low-E中空玻璃(在线)","","","无色",47,15,28,8,0.38],
            ["辐射率≤0.25Low-E中空玻璃(在线)","","","无色",50,16,29,8,0.37],
            ["辐射率≤0.15Low-E中空玻璃(离线)","反射颜色","无色","无色",52,14,33,26,0.44],
            ["辐射率≤0.15Low-E中空玻璃(离线)","反射颜色","绿色","绿色",42,11,19,9,0.30],
            ["辐射率≤0.15Low-E中空玻璃(离线)","反射颜色","蓝绿色","绿色",45,19,21,12,0.31],
            ["辐射率≤0.15Low-E中空玻璃(离线)","反射颜色","蓝色","无色",57,34,37,30,0.50],
            ["辐射率≤0.15Low-E中空玻璃(离线)","反射颜色","淡蓝色","无色",62,16,38,28,0.50],
            ["辐射率≤0.15Low-E中空玻璃(离线)","反射颜色","银蓝色","无色",46,33,28,40,0.37],
            ["辐射率≤0.15Low-E中空玻璃(离线)","反射颜色","银灰色","无色",47,41,26,50,0.34],
            ["辐射率≤0.15Low-E中空玻璃(离线)","反射颜色","金色","无色",40,22,24,45,0.32]
数据是这样
泡泡鱼_ 2021-03-31
  • 打赏
  • 举报
回复
引用 13 楼 wenlong_15 的回复:
我自己做 。
嗯,要改的地方并不多。就是得自己写,单看代码,是看不成自己的
wenlong_15 2021-03-31
  • 打赏
  • 举报
回复
我自己做 。
wenlong_15 2021-03-31
  • 打赏
  • 举报
回复
引用 11 楼 泡泡鱼_ 的回复:
……示例和方法都告诉你了呀
我的想法并不是要完全合并,是数据错位了,
泡泡鱼_ 2021-03-31
  • 打赏
  • 举报
回复
……示例和方法都告诉你了呀
泡泡鱼_ 2021-03-30
  • 打赏
  • 举报
回复
引用 8 楼 wenlong_15 的回复:
[quote=引用 5 楼 泡泡鱼_ 的回复:]trIndex应该是换成tdIndex才对,也更好理解
如果行和列数据有相同的会有问题,这样的不好解决吧?[/quote] 至少不能靠合并去解决,table解决不了的。 你可以尝试使用样式去解决,达到一个相对的解决 我示例中是优先合并列,在合并行的时候,是主动排除了已经合并过的列的,你需要将条件去除后,然后再针对是否有合并过列做不同的,合并过的,则将name='$$$'//这里面的$$$是一个固定的;未合并过的,还是按原先的处理 然后模板中: 控制内容输出:{{td.name=='$$$'? '' : td.name}} 然后就是解决样式了,你可以给单元格设定样式,关键在于边框样式,比如,你可以设置当td.name=='$$$'时,下边框为0。这样,可以达到一个视觉上的合并
wenlong_15 2021-03-30
  • 打赏
  • 举报
回复
引用 5 楼 泡泡鱼_ 的回复:
trIndex应该是换成tdIndex才对,也更好理解
如果行和列数据有相同的会有问题,这样的不好解决吧?
泡泡鱼_ 2021-03-29
  • 打赏
  • 举报
回复
trIndex应该是换成tdIndex才对,也更好理解
泡泡鱼_ 2021-03-29
  • 打赏
  • 举报
回复
试下这是不是你想要的: 因为要使用v-if="itemTd.name"去控制输出,所以将v-for前置到template中了

<template>
  <div>
    <table width="100%" cellspan="0">
      <tr v-for="(itemTr, indexTr) in tableData" :key="indexTr">
        <template v-for="(itemTd, indexTd) in itemTr">
        <td
          :rowspan="itemTd.rowSpan"
          :colspan="itemTd.colSpan"
          :key="indexTd"
          v-if="itemTd.name"
        >
          {{ itemTd.name }}
        </td>
        </template>
      </tr>
    </table>
  </div>
</template>
<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      tableData: [
        ['周一', '周一', '周一', '周四', '周五', '周六'],
        ['语文', '数学', '英语', '历史', '物理', '化学'],
        ['语文', '英语', '数学', '物理', '历史', '体育'],
        ['语文', '英语', '物理', '数学', '体育', '历史'],
        ['数学', '语文', '化学', '物理', '历史', '体育'],
        ['数学', '语文', '化学', '物理', '体育', '历史']
      ]
    }
  },

  created () {
    this.tableData = this.transformData()
    // console.log(JSON.stringify(this.tableData, null, 2))
  },

  methods: {
    transformData () {
      const newData = []
      // 先做列合并
      this.tableData.forEach(trs => {
        const newTr = []
        let col = {}
        trs.forEach((td, tdIndex) => {
          if (td in col) {
            newTr[col[td]].colSpan++
            newTr.push({ name: '', rowSpan: 1, colSpan: 1 })
          } else {
            col = { [td]: tdIndex }
            newTr.push({ name: td, rowSpan: 1, colSpan: 1 })
          }
        })
        newData.push(newTr)
      })
      // 做行合并
      const row = []
      newData.forEach((trs, index) => {
        trs.forEach((td, trIndex) => {
          if (td.name) {
            if (row[trIndex] && (td.name in row[trIndex]) && (newData[row[trIndex][td.name]][trIndex].colSpan === 1)) {
              newData[row[trIndex][td.name]][trIndex].rowSpan++
              td.name = ''
            } else {
              row[trIndex] = { [td.name]: index }
            }
          }
        })
      })

      return newData
    }
  }
}
</script>
<style scoped>
table {
  border: 1px solid #666;
}

table td {
  border-bottom: 1px solid #666;
  border-right: 1px solid #666;
}
</style>

wenlong_15 2021-03-29
  • 打赏
  • 举报
回复
tableData: [ ["周一", "周一", "周一", "周四", "周五", "周六"], ["语文", "数学", "英语", "历史", "物理", "化学"], ["语文", "英语", "数学", "物理", "历史", "体育"], ["语文", "英语", "物理", "数学", "体育", "历史"], ["数学", "语文", "化学", "物理", "历史", "体育"], ["数学", "语文", "化学", "物理", "体育", "历史"], ] 数据是这样的,不会行和列同时存在,
wenlong_15 2021-03-29
  • 打赏
  • 举报
回复
你的比我的写得好,
wenlong_15 2021-03-29
  • 打赏
  • 举报
回复
谢谢,我自己写了一个,但功能没有你的好。
<!-- 地面弹出框 -->
<template>
  <div>
    <el-dialog width="40%" :visible.sync="hdVisible">
      <div slot="title" class="dialog-title">
        <i class="el-icon-warning-outline"></i>
        <span class="title-text">{{ helpData.name }}</span>
      </div>
      <table class="help-table">
        <tr v-for="(itemTr, indexTr) in tableData" :key="indexTr">
          <td
            :colspan="itemTd.colspan"
            :rowspan="itemTd.rowspan"
            v-for="(itemTd, indexTd) in itemTr"
            :key="indexTd"
            @click="selectVal(itemTd.name)"
            :class="typeof itemTd.name === 'number' ? 'selectable' : ''"
          >
            {{ itemTd.name }}
          </td>
        </tr>
      </table>
      <div class="description">{{ helpData.description }}</div>
    </el-dialog>
  </div>
</template>
<script>
import HelpDocument from "@/utils/helpdocument.json";
export default {
  data() {
    return {
      //帮助文档
      HelpDocument,
      //帮助文档显示或隐藏
      hdVisible: false,
      //帮助文档关键词
      helpKey: "",
      //数据
      helpData: "",
      tableData: [],
    };
  },
  created() {},
  computed: {},
  watch: {
    // 监听页面显示隐藏
    hdVisible: {
      handler(newVal) {
        if (newVal == true) {
        }
      },
      deep: true,
    },
  },
  methods: {
    selectVal(value) {
      if (typeof value === "number") {
        //向父组件传单元格的值
        this.$emit("parentMethod", { name: this.helpKey, value });
        this.hdVisible = false;
      }
    },

    // 控制显示隐藏 val:add  or  edit
    helpDocumentVisible(bool) {
      if (bool) {
        this.getHelpDocumentData(this.helpKey);
      }
      this.hdVisible = bool;
    },

    //根据关键词 获取帮助文档数据
    getHelpDocumentData(helpKey) {
      for (let key in HelpDocument) {
        if (key === helpKey) {
          this.helpData = HelpDocument[key];
          //表格数据处理
          this.tableData = this.colspanData(HelpDocument[key].tableData);
          break;
        }
      }
    },

    //合并行和列
    colspanData(data) {
      //合并行
      let colspanData = [];
      for (let i = 0; i < data.length; i++) {
        let rowsArray = [];
        second: for (let j = 0; j < data[i].length; j++) {
          let obj = {
            name: data[i][j],
            colspan: 1, //列
            rowspan: 1, //行
          };
          if (rowsArray.length > 0) {
            for (let k = 0; k < rowsArray.length; k++) {
              if (data[i][j] === rowsArray[k].name) {
                rowsArray[k].colspan++;
                continue second;
              }
            }
          }
          rowsArray.push(obj);
        }
        colspanData.push(rowsArray);
      }
      //合并列
      return this.rowspanData(colspanData);
    },

    //合并列
    rowspanData(data) {
      for (let i = data.length; i > 0; i--) {
        if (data[i - 2]) {
          if (data[i - 1].length === data[i - 2].length) {
            for (let j = data[i - 1].length; j > 0; j--) {
              if (typeof data[i - 1][j - 1].name != "number") {
                if (data[i - 1][j - 1].name === data[i - 2][j - 1].name) {
                  //如果与上一个元素相同,上一个元素的rowspan+当前的rowspan值
                  data[i - 2][j - 1].rowspan += data[i - 1][j - 1].rowspan;
                  //如果与上一个元素相同,删除当前元素
                  data[i - 1].splice(j - 1, 1);
                }
              }
            }
          }
        }
      }
      return data;
    },
  },
};
</script>
<style lang="scss" scoped>
.help-table {
  width: 100%;
  border: 1px solid #ddd;
  background: #f6f6f6;
  line-height: 2em;
  border-collapse: collapse;
  padding: 0;
  th,
  td {
    text-align: center;
    border-right: 1px solid #ddd;
  }
  td {
    border-top: 1px solid #ddd;
  }
  th.end,
  td.end {
    border-right: 0;
  }
  .selectable {
    background: #fff;
  }
}
.description {
  padding: 10px 0;
}
</style>
泡泡鱼_ 2021-03-28
  • 打赏
  • 举报
回复
引用 1 楼 wenlong_15 的回复:
自己做了几天,还是没做出来。公司项目,求救csdn了
['周一', '周二', '周三', '周四', '周五', '周六'], ['语文', '语文', '英语', '历史', '物理', '化学'], ['语文', '英语', '数学', '物理', '历史', '体育'], ['语文', '英语', '物理', '数学', '体育', '历史'], ['数学', '语文', '化学', '物理', '历史', '体育'], ['数学', '语文', '化学', '物理', '体育', '历史'] 假如你数据是这样子,你用table怎么合并呀?周一的1,2,3节全是语文,但周二的第1节也是语文,想同时合并,按你原有的想法那样,在数据层面上可以,但table合并不了的呀,table会异常。所以,行和列,你必须得有一个优先合并原则
wenlong_15 2021-03-28
  • 打赏
  • 举报
回复
自己做了几天,还是没做出来。公司项目,求救csdn了

87,994

社区成员

发帖
与我相关
我的任务
社区描述
Web 开发 JavaScript
社区管理员
  • JavaScript
  • 无·法
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧