定制软件开发Element UI 的 table 单元格合并

定制软件开发项目中遇到表格单元格定制软件开发合并的需求,定制软件开发在此记录整个解决过程。

定制软件开发项目使用的是 Element UI,定制软件开发表格使用的是 table 组件。Element UI 的 table 定制软件开发表格组件中对单元格进行合并,需要使用 table 组件的 span-method 属性。

先看一张成果图(完整代码放在末尾):

解决思路:

1、格式化后台返回的数据(根据实际数据格式处理)

项目后台返回的数据格式为,这里做简化展示:

  1. [
  2. {
  3. 'column1': '111',
  4. 'column2': '222',
  5. 'column3': '333',
  6. 'children1': [
  7. {
  8. 'column6': 666,
  9. 'column4': '4440',
  10. 'column5': '5550',
  11. 'children2': [
  12. {
  13. 'column7': '77701',
  14. 'column8': '88801',
  15. 'column9': '99901'
  16. }
  17. ]
  18. }
  19. ]
  20. }
  21. ]

需要先将树结构数据转为一维数组:

  1. // table 表格数据初始化处理,将树结构数据转为一维数组
  2. handleData(data, parentId) {
  3. data.map((res, index) => {
  4. var obj = {
  5. id: parentId
  6. }
  7. for (const key in res) {
  8. const isarr = Object.values(res).find((age) => {
  9. return Array.isArray(age)
  10. })
  11. if (isarr) {
  12. if (Array.isArray(res[key])) {
  13. for (let i = 0; i < res[key].length; i++) {
  14. Object.assign(obj, res[key][i])
  15. data.push(obj)
  16. res[key].splice(i, 1)
  17. if (res[key].length === 0) {
  18. data.splice(index, 1)
  19. }
  20. this.handleData(data, parentId)
  21. }
  22. } else {
  23. Object.assign(obj, { [key]: res[key] })
  24. }
  25. }
  26. }
  27. })
  28. return data
  29. }

因为后台返回的数据里没有唯一标识符,所以需要单独添加一个唯一标识表示转换为一维数组的数据是出自同一组树结构里。故此处在展开时单独加了一个 id 属性,用来代替唯一标识。如果后台返回的数据格式就是一个一维数组,可跳过数据格式化步骤。

2、在 data 中定义数据,需要合并几列就定义几个数组和索引

  1. data() {
  2. return {
  3. tableData: [],
  4. // 合并单元格
  5. column1Arr: [], // column1
  6. column1Index: 0, // column1索引
  7. column2Arr: [], // column2
  8. column2Index: 0, // column2索引
  9. column3Arr: [], // column3
  10. column3Index: 0, // column3索引
  11. column4Arr: [], // column4
  12. column4Index: 0, // column4
  13. column5Arr: [], // column5
  14. column5Index: 0, // column5索引
  15. column6Arr: [], // column6
  16. column6Index: 0 // column6索引
  17. }
  18. }

 3、定义合并函数

以第一行为基准,一层层对比,参数 data 就是格式化以后的表格数据,以每个数据里的唯一标识 id 作为合并的参照字段:

  1. // 初始化合并行数组
  2. mergeInit() {
  3. this.column1Arr = [] // column1
  4. this.column1Index = 0 // column1索引
  5. this.column2Arr = [] // column2
  6. this.column2Index = 0 // column2索引
  7. this.column3Arr = [] // column3
  8. this.column3Index = 0 // column3索引
  9. this.column4Arr = [] // column4
  10. this.column4Index = 0 // column4索引
  11. this.column5Arr = [] // column5
  12. this.column5Index = 0 // column5索引
  13. this.column6Arr = [] // column6
  14. this.column6Index = 0 // column6索引
  15. },
  16. // 合并表格
  17. mergeTable(data) {
  18. this.mergeInit()
  19. if (data.length > 0) {
  20. for (var i = 0; i < data.length; i++) {
  21. if (i === 0) {
  22. // 第一行必须存在,以第一行为基准
  23. this.column1Arr.push(1) // column1
  24. this.column1Index = 0
  25. this.column2Arr.push(1) // column2
  26. this.column2Index = 0
  27. this.column3Arr.push(1) // column3
  28. this.column3Index = 0
  29. this.column4Arr.push(1) // column4
  30. this.column4Index = 0
  31. this.column5Arr.push(1) // column5
  32. this.column5Index = 0
  33. this.column6Arr.push(1) // column6
  34. this.column6Index = 0
  35. } else {
  36. // 判断当前元素与上一元素是否相同
  37. // column1
  38. if (
  39. data[i].column1 === data[i - 1].column1 &&
  40. data[i].id === data[i - 1].id
  41. ) {
  42. this.column1Arr[this.column1Index] += 1
  43. this.column1Arr.push(0)
  44. } else {
  45. this.column1Arr.push(1)
  46. this.column1Index = i
  47. }
  48. // column2
  49. if (
  50. data[i].column2 === data[i - 1].column2 &&
  51. data[i].id === data[i - 1].id
  52. ) {
  53. this.column2Arr[this.column2Index] += 1
  54. this.column2Arr.push(0)
  55. } else {
  56. this.column2Arr.push(1)
  57. this.column2Index = i
  58. }
  59. // column3
  60. if (
  61. data[i].column3 === data[i - 1].column3 &&
  62. data[i].id === data[i - 1].id
  63. ) {
  64. this.column3Arr[this.column3Index] += 1
  65. this.column3Arr.push(0)
  66. } else {
  67. this.column3Arr.push(1)
  68. this.column3Index = i
  69. }
  70. // column4
  71. if (
  72. data[i].column4 === data[i - 1].column4 &&
  73. data[i].id === data[i - 1].id
  74. ) {
  75. this.column4Arr[this.column4Index] += 1
  76. this.column4Arr.push(0)
  77. } else {
  78. this.column4Arr.push(1)
  79. this.column4Index = i
  80. }
  81. // column5
  82. if (
  83. data[i].column5 === data[i - 1].column5 &&
  84. data[i].column4 === data[i - 1].column4 &&
  85. data[i].id === data[i - 1].id
  86. ) {
  87. this.column5Arr[this.column5Index] += 1
  88. this.column5Arr.push(0)
  89. } else {
  90. this.column5Arr.push(1)
  91. this.column5Index = i
  92. }
  93. // column6
  94. if (
  95. data[i].column6 === data[i - 1].column6 &&
  96. data[i].column4 === data[i - 1].column4 &&
  97. data[i].id === data[i - 1].id
  98. ) {
  99. this.column6Arr[this.column6Index] += 1
  100. this.column6Arr.push(0)
  101. } else {
  102. this.column6Arr.push(1)
  103. this.column6Index = i
  104. }
  105. }
  106. }
  107. }
  108. },

注意,同一组数据里可能会有多个  children1 或者 children2,这时合并的时候会有多个条件进行判断:

 

 4、table 组件属性 span-method 的单元格合并方法:

  1. handleSpanMethod({ row, column, rowIndex, columnIndex }) {
  2. if (columnIndex === 0 || columnIndex === 1) {
  3. // 第一列 column1
  4. const _row_1 = this.column1Arr[rowIndex]
  5. const _col_1 = _row_1 > 0 ? 1 : 0
  6. return {
  7. rowspan: _row_1,
  8. colspan: _col_1
  9. }
  10. } else if (columnIndex === 2) {
  11. // 第二列 column2
  12. const _row_2 = this.column2Arr[rowIndex]
  13. const _col_2 = _row_2 > 0 ? 1 : 0
  14. return {
  15. rowspan: _row_2,
  16. colspan: _col_2
  17. }
  18. } else if (columnIndex === 3) {
  19. // 第三列 column3
  20. const _row_2 = this.column3Arr[rowIndex]
  21. const _col_2 = _row_2 > 0 ? 1 : 0
  22. return {
  23. rowspan: _row_2,
  24. colspan: _col_2
  25. }
  26. } else if (columnIndex === 4) {
  27. // 第四列 column4
  28. const _row_2 = this.column4Arr[rowIndex]
  29. const _col_2 = _row_2 > 0 ? 1 : 0
  30. return {
  31. rowspan: _row_2,
  32. colspan: _col_2
  33. }
  34. } else if (columnIndex === 5) {
  35. // 第五列 column5
  36. const _row_2 = this.column5Arr[rowIndex]
  37. const _col_2 = _row_2 > 0 ? 1 : 0
  38. return {
  39. rowspan: _row_2,
  40. colspan: _col_2
  41. }
  42. } else if (columnIndex === 6) {
  43. // 第六列 column6
  44. const _row_2 = this.column6Arr[rowIndex]
  45. const _col_2 = _row_2 > 0 ? 1 : 0
  46. return {
  47. rowspan: _row_2,
  48. colspan: _col_2
  49. }
  50. }
  51. }

至此,整个单元格合并就完成了!

如果觉得写得还不错,还请点赞支持,感谢感谢感谢!!!

完整代码:

  1. <template>
  2. <div class="table-wrap">
  3. <el-table
  4. :data="tableData"
  5. :span-method="handleSpanMethod"
  6. :cell-style="{ background: '#FFFFFF' }"
  7. border
  8. style="width: 100%"
  9. >
  10. <el-table-column prop="id" label="序号" align="center" width="80">
  11. <template slot-scope="scope">
  12. {{ scope.row.id + 1 }}
  13. </template>
  14. </el-table-column>
  15. <el-table-column prop="column1" label="column1" align="center" />
  16. <el-table-column prop="column2" label="column2" align="center" />
  17. <el-table-column prop="column3" label="column3" align="center" />
  18. <el-table-column prop="column4" label="column4" align="center" />
  19. <el-table-column prop="column5" label="column5" align="center" />
  20. <el-table-column prop="column6" label="column6" align="center" />
  21. <el-table-column prop="column7" label="column7" align="center" />
  22. <el-table-column prop="column8" label="column8" align="center" />
  23. <el-table-column prop="column9" label="column9" align="center" />
  24. </el-table>
  25. </div>
  26. </template>
  27. <script>
  28. export default {
  29. name: 'CellMerge',
  30. data() {
  31. return {
  32. tableData: [],
  33. // 合并单元格
  34. column1Arr: [], // column1
  35. column1Index: 0, // column1索引
  36. column2Arr: [], // column2
  37. column2Index: 0, // column2索引
  38. column3Arr: [], // column3
  39. column3Index: 0, // column3索引
  40. column4Arr: [], // column4
  41. column4Index: 0, // column4
  42. column5Arr: [], // column5
  43. column5Index: 0, // column5索引
  44. column6Arr: [], // column6
  45. column6Index: 0 // column6索引
  46. }
  47. },
  48. mounted() {
  49. this.initTableData()
  50. },
  51. methods: {
  52. // 初始化表格数据
  53. initTableData() {
  54. const newTableData = [
  55. {
  56. 'column1': '111',
  57. 'column2': '222',
  58. 'column3': '333',
  59. 'children1': [
  60. {
  61. 'column6': 666,
  62. 'column4': '4440',
  63. 'column5': '5550',
  64. 'children2': [
  65. {
  66. 'column7': '77701',
  67. 'column8': '88801',
  68. 'column9': '99901'
  69. },
  70. {
  71. 'column7': '77702',
  72. 'column8': '88802',
  73. 'column9': '99902'
  74. },
  75. {
  76. 'column7': '77703',
  77. 'column8': '88803',
  78. 'column9': '99903'
  79. }
  80. ]
  81. },
  82. {
  83. 'column6': 666,
  84. 'column4': '4441',
  85. 'column5': '5551',
  86. 'children2': [
  87. {
  88. 'column7': '77711',
  89. 'column8': '88811',
  90. 'column9': '99911'
  91. }
  92. ]
  93. },
  94. {
  95. 'column6': 666,
  96. 'column4': '4442',
  97. 'column5': '5552',
  98. 'children2': [
  99. {
  100. 'column7': '77721',
  101. 'column8': '88821',
  102. 'column9': '99921'
  103. },
  104. {
  105. 'column7': '77722',
  106. 'column8': '88822',
  107. 'column9': '99922'
  108. }
  109. ]
  110. }
  111. ]
  112. },
  113. {
  114. 'column1': '111',
  115. 'column2': '222',
  116. 'column3': '333',
  117. 'children1': [
  118. {
  119. 'column6': 666,
  120. 'column4': '4440',
  121. 'column5': '5550',
  122. 'children2': [
  123. {
  124. 'column7': '77701',
  125. 'column8': '88801',
  126. 'column9': '99901'
  127. }
  128. ]
  129. },
  130. {
  131. 'column6': 666,
  132. 'column4': '4441',
  133. 'column5': '5551',
  134. 'children2': [
  135. {
  136. 'column7': '77711',
  137. 'column8': '88811',
  138. 'column9': '99911'
  139. },
  140. {
  141. 'column7': '77712',
  142. 'column8': '88812',
  143. 'column9': '99912'
  144. }
  145. ]
  146. }
  147. ]
  148. },
  149. {
  150. 'column1': '111',
  151. 'column2': '222',
  152. 'column3': '333',
  153. 'children1': [
  154. {
  155. 'column6': 666,
  156. 'column4': '4440',
  157. 'column5': '5550',
  158. 'children2': [
  159. {
  160. 'column7': '77701',
  161. 'column8': '88801',
  162. 'column9': '99901'
  163. },
  164. {
  165. 'column7': '77702',
  166. 'column8': '88802',
  167. 'column9': '99902'
  168. },
  169. {
  170. 'column7': '77703',
  171. 'column8': '88803',
  172. 'column9': '99903'
  173. }
  174. ]
  175. },
  176. {
  177. 'column6': 666,
  178. 'column4': '4441',
  179. 'column5': '5551',
  180. 'children2': [
  181. {
  182. 'column7': '77711',
  183. 'column8': '88811',
  184. 'column9': '99911'
  185. }
  186. ]
  187. }
  188. ]
  189. }
  190. ]
  191. this.tableData = []
  192. newTableData.map((res, index) => {
  193. const parentId = index
  194. this.tableData.push.apply(
  195. this.tableData,
  196. this.handleData([res], parentId)
  197. )
  198. })
  199. this.mergeTable(this.tableData)
  200. },
  201. // table 表格数据初始化处理,将树结构数据转为一维数组
  202. handleData(data, parentId) {
  203. data.map((res, index) => {
  204. var obj = {
  205. id: parentId
  206. }
  207. for (const key in res) {
  208. const isarr = Object.values(res).find((age) => {
  209. return Array.isArray(age)
  210. })
  211. if (isarr) {
  212. if (Array.isArray(res[key])) {
  213. for (let i = 0; i < res[key].length; i++) {
  214. Object.assign(obj, res[key][i])
  215. data.push(obj)
  216. res[key].splice(i, 1)
  217. if (res[key].length === 0) {
  218. data.splice(index, 1)
  219. }
  220. this.handleData(data, parentId)
  221. }
  222. } else {
  223. Object.assign(obj, { [key]: res[key] })
  224. }
  225. }
  226. }
  227. })
  228. return data
  229. },
  230. // 初始化合并行数组
  231. mergeInit() {
  232. this.column1Arr = [] // column1
  233. this.column1Index = 0 // column1索引
  234. this.column2Arr = [] // column2
  235. this.column2Index = 0 // column2索引
  236. this.column3Arr = [] // column3
  237. this.column3Index = 0 // column3索引
  238. this.column4Arr = [] // column4
  239. this.column4Index = 0 // column4索引
  240. this.column5Arr = [] // column5
  241. this.column5Index = 0 // column5索引
  242. this.column6Arr = [] // column6
  243. this.column6Index = 0 // column6索引
  244. },
  245. // 合并表格
  246. mergeTable(data) {
  247. this.mergeInit()
  248. if (data.length > 0) {
  249. for (var i = 0; i < data.length; i++) {
  250. if (i === 0) {
  251. // 第一行必须存在,以第一行为基准
  252. this.column1Arr.push(1) // column1
  253. this.column1Index = 0
  254. this.column2Arr.push(1) // column2
  255. this.column2Index = 0
  256. this.column3Arr.push(1) // column3
  257. this.column3Index = 0
  258. this.column4Arr.push(1) // column4
  259. this.column4Index = 0
  260. this.column5Arr.push(1) // column5
  261. this.column5Index = 0
  262. this.column6Arr.push(1) // column6
  263. this.column6Index = 0
  264. } else {
  265. // 判断当前元素与上一元素是否相同
  266. // column1
  267. if (
  268. data[i].column1 === data[i - 1].column1 &&
  269. data[i].id === data[i - 1].id
  270. ) {
  271. this.column1Arr[this.column1Index] += 1
  272. this.column1Arr.push(0)
  273. } else {
  274. this.column1Arr.push(1)
  275. this.column1Index = i
  276. }
  277. // column2
  278. if (
  279. data[i].column2 === data[i - 1].column2 &&
  280. data[i].id === data[i - 1].id
  281. ) {
  282. this.column2Arr[this.column2Index] += 1
  283. this.column2Arr.push(0)
  284. } else {
  285. this.column2Arr.push(1)
  286. this.column2Index = i
  287. }
  288. // column3
  289. if (
  290. data[i].column3 === data[i - 1].column3 &&
  291. data[i].id === data[i - 1].id
  292. ) {
  293. this.column3Arr[this.column3Index] += 1
  294. this.column3Arr.push(0)
  295. } else {
  296. this.column3Arr.push(1)
  297. this.column3Index = i
  298. }
  299. // column4
  300. if (
  301. data[i].column4 === data[i - 1].column4 &&
  302. data[i].id === data[i - 1].id
  303. ) {
  304. this.column4Arr[this.column4Index] += 1
  305. this.column4Arr.push(0)
  306. } else {
  307. this.column4Arr.push(1)
  308. this.column4Index = i
  309. }
  310. // column5
  311. if (
  312. data[i].column5 === data[i - 1].column5 &&
  313. data[i].column4 === data[i - 1].column4 &&
  314. data[i].id === data[i - 1].id
  315. ) {
  316. this.column5Arr[this.column5Index] += 1
  317. this.column5Arr.push(0)
  318. } else {
  319. this.column5Arr.push(1)
  320. this.column5Index = i
  321. }
  322. // column6
  323. if (
  324. data[i].column6 === data[i - 1].column6 &&
  325. data[i].column4 === data[i - 1].column4 &&
  326. data[i].id === data[i - 1].id
  327. ) {
  328. this.column6Arr[this.column6Index] += 1
  329. this.column6Arr.push(0)
  330. } else {
  331. this.column6Arr.push(1)
  332. this.column6Index = i
  333. }
  334. }
  335. }
  336. }
  337. },
  338. handleSpanMethod({ row, column, rowIndex, columnIndex }) {
  339. if (columnIndex === 0 || columnIndex === 1) {
  340. // 第一列 column1
  341. const _row_1 = this.column1Arr[rowIndex]
  342. const _col_1 = _row_1 > 0 ? 1 : 0
  343. return {
  344. rowspan: _row_1,
  345. colspan: _col_1
  346. }
  347. } else if (columnIndex === 2) {
  348. // 第二列 column2
  349. const _row_2 = this.column2Arr[rowIndex]
  350. const _col_2 = _row_2 > 0 ? 1 : 0
  351. return {
  352. rowspan: _row_2,
  353. colspan: _col_2
  354. }
  355. } else if (columnIndex === 3) {
  356. // 第三列 column3
  357. const _row_2 = this.column3Arr[rowIndex]
  358. const _col_2 = _row_2 > 0 ? 1 : 0
  359. return {
  360. rowspan: _row_2,
  361. colspan: _col_2
  362. }
  363. } else if (columnIndex === 4) {
  364. // 第四列 column4
  365. const _row_2 = this.column4Arr[rowIndex]
  366. const _col_2 = _row_2 > 0 ? 1 : 0
  367. return {
  368. rowspan: _row_2,
  369. colspan: _col_2
  370. }
  371. } else if (columnIndex === 5) {
  372. // 第五列 column5
  373. const _row_2 = this.column5Arr[rowIndex]
  374. const _col_2 = _row_2 > 0 ? 1 : 0
  375. return {
  376. rowspan: _row_2,
  377. colspan: _col_2
  378. }
  379. } else if (columnIndex === 6) {
  380. // 第六列 column6
  381. const _row_2 = this.column6Arr[rowIndex]
  382. const _col_2 = _row_2 > 0 ? 1 : 0
  383. return {
  384. rowspan: _row_2,
  385. colspan: _col_2
  386. }
  387. }
  388. }
  389. }
  390. }
  391. </script>
  392. <style lang="scss" scoped>
  393. .table-wrap {
  394. width: 100%;
  395. height: 100%;
  396. padding: 20px;
  397. }
  398. </style>

 

网站建设定制开发 软件系统开发定制 定制软件开发 软件开发定制 定制app开发 app开发定制 app开发定制公司 电商商城定制开发 定制小程序开发 定制开发小程序 客户管理系统开发定制 定制网站 定制开发 crm开发定制 开发公司 小程序开发定制 定制软件 收款定制开发 企业网站定制开发 定制化开发 android系统定制开发 定制小程序开发费用 定制设计 专注app软件定制开发 软件开发定制定制 知名网站建设定制 软件定制开发供应商 应用系统定制开发 软件系统定制开发 企业管理系统定制开发 系统定制开发