Foreword
Since I am using Vue, I think that MVVM needs to be data-driven, so I consider doing tricks in the Model instead of rendering the data and then doing DOM operations. Of course, basic CSS is still required. Therefore this method is valid for all data-driven frameworks, such as Angular and React.
Implementation idea
The code of the original normal table looks like this:
<tr v-for="item in items"> <td width="3%">{{ $index + 1 }}</td> <td width="15%">{{item.bsO_Name}}</td> <td width="8%" :class="{'overtime': overtime(item.GathDt)}">{{item.GathDt | time}}</td> <td width="5%">{{item.F1}}</td> <td width="5%">{{item.F2}}</td> <td width="5%">{{item.F4}}</td> <td width="5%">{{item.F3}}</td> <td width="5%">{{item.F5}}</td> <td width="5%">{{item.F6}}</td> <td width="5%">{{item.F7}}</td> <td width="5%">{{item.F8}}</td> <td width="5%">{{item.F9}}</td> <td width="5%">{{item.F10}}</td> </tr>
First use the normal table for testing. The native
Because if the next row is still rendered, it will be squeezed out. Therefore, the merged cells below need to be hidden, which can be controlled by display: none; css.
Therefore, each
The code becomes like this
<tr v-for="item in items"> <td width="3%">{{ $index + 1 }}</td> <td width="10%" :rowspan="item.bsO_Namespan" :class="{hidden: item.bsO_Namedis}">{{item.bsO_Name}}</td> <td width="8%" :rowspan="item.GathDtspan" :class="{hidden: item.GathDtdis}" :class="{overtime: overtime(item.GathDt)}">{{item.GathDt | time}}</td> <td width="5%" :rowspan="item.F1span" :class="{hidden: item.F1dis}">{{item.F1}}</td> <td width="5%" :rowspan="item.F2span" :class="{hidden: item.F2dis}">{{item.F2}}</td> <td width="5%" :rowspan="item.F3span" :class="{hidden: item.F3dis}">{{item.F3}}</td> <td width="5%" :rowspan="item.F4span" :class="{hidden: item.F4dis}">{{item.F4}}</td> <td width="5%" :rowspan="item.F5span" :class="{hidden: item.F5dis}">{{item.F5}}</td> <td width="10%" :rowspan="item.F6span" :class="{hidden: item.F6dis}">{{item.F6}}</td> <td width="8%" :rowspan="item.F7span" :class="{hidden: item.F7dis}" :class="{overtime: overtime(item.F7)}">{{item.F7 | time}}</td> <td width="5%" :rowspan="item.F8span" :class="{hidden: item.F8dis}">{{item.F8}}</td> <td width="5%" :rowspan="item.F9span" :class="{hidden: item.F9dis}">{{item.F9}}</td> <td width="5%" :rowspan="item.F10span" :class="{hidden: item.F10dis}">{{item.F10}}</td> <td width="5%" :rowspan="item.F11span" :class="{hidden: item.F11dis}">{{item.F11}}</td> </tr>
Among them, these two attributes have some characteristics:
The rowspan of the cell to be displayed is a value of >1, and the next number of rows are recorded
To be displayed The cell display is true
The next cell that is not displayed has a rowspan of 1 and the display is false
The cell with only one row of data has a rowspan of 1 and the display is true
In fact, it is to design an algorithm, for For the input table array, add two attributes to each data item, rowspan and display, and calculate the number of rows whose rowspan value is
the following same values in this column, and calculate whether the display value is displayed based on the rowspan value. Finally, the changed array is output.
Solve the sample code
function combineCell(list) { for (field in list[0]) { var k = 0; while (k < list.length) { list[k][field + 'span'] = 1; list[k][field + 'dis'] = false; for (var i = k + 1; i <= list.length - 1; i++) { if (list[k][field] == list[i][field] && list[k][field] != '') { list[k][field + 'span']++; list[k][field + 'dis'] = false; list[i][field + 'span'] = 1; list[i][field + 'dis'] = true; } else { break; } } k = i; } } return list; }
Summary
The code is actually very short and simple. It mainly relies on the idea of kmp, defining a pointer k, starting to point to the first value, and then comparing downwards. For rowspan and display settings,
If different values are encountered, it will be judged as jumping out, and the next loop will be performed. The pointer k will be notified plus the number of rows calculated in the process, jump will be performed, and then the next cell will be compared. Value, the same principle as kmp's pointer jump to determine the same string.
Use the combineCell() function to filter the data returned from the network request, append the corresponding value, and then assign the value to the array monitored by vue.
In fact, this method is not only applicable to vue, but also to data-driven frameworks, including Angular and React. If you want to achieve table merging, just filter the values returned by the request.