Vue.js中el-table同Load number对应Product name行合并实现咨询
Hey there! Let's work through this row merging problem for your Element UI table. The core solution uses Element's built-in span-method property to control cell spanning, plus a bit of data pre-processing to calculate how many rows each product name cell should cover. Here's a step-by-step fix tailored to your existing code:
Step 1: Preprocess Your Table Data
First, we need to add a property to each row that tells us how many rows the Product Name cell should span (or if it should be hidden). We'll group rows by po_number (your Load Number) and mark the first row of each group to span all rows in the group, while hiding the rest.
Add this method to your component:
// Calculate span values for product name cells handleMergeTableData(rawData) { if (!rawData.length) return []; // Sort data by load number to ensure same numbers are consecutive // Adjust to `a.po_number - b.po_number` if your load number is numeric const sortedData = [...rawData].sort((a, b) => a.po_number.localeCompare(b.po_number)); // Group rows by load number and track group sizes const loadNumberGroups = {}; sortedData.forEach(row => { if (!loadNumberGroups[row.po_number]) { loadNumberGroups[row.po_number] = []; } loadNumberGroups[row.po_number].push(row); }); // Add productSpan property to each row const mergedData = []; Object.values(loadNumberGroups).forEach(group => { const groupSize = group.length; group.forEach((row, index) => { mergedData.push({ ...row, // First row in group spans all rows; others are hidden (span 0) productSpan: index === 0 ? groupSize : 0 }); }); }); return mergedData; }
Then process your original data when it's loaded (e.g., in the created hook or after fetching data):
// Assume your original table data is stored in this.tableData this.mergedTableData = this.handleMergeTableData(this.tableData);
Step 2: Update the Table with Span Logic
Modify your <el-table> to use the processed data and add the span-method that applies our merging rules:
<el-table :data="mergedTableData" :span-method="handleCellSpan" > <el-table-column prop="product" sortable="custom" :label="$t('Product name')" v-if="checkedCols.indexOf('Product Name') >= 0" > </el-table-column> <el-table-column prop="po_number" sortable="custom" :label="$t('Load number')" v-if="checkedCols.indexOf('Load Number') >= 0" > <template slot-scope="scope"> <a target="_blank" href="#" @click="openPhaseIUrl(scope.row.po_number, 'load')"> {{scope.row.po_number}} </a> </template> </el-table-column> </el-table>
Step 3: Implement the Span Method
Add this method to your component to define how each cell should span:
handleCellSpan({ row, column }) { // Target the Product Name column using its prop (more reliable than column index) if (column.prop === 'product') { return { rowspan: row.productSpan, // Use our pre-calculated span value colspan: 1 // Keep column width unchanged }; } // For all other columns, keep default 1x1 spanning return { rowspan: 1, colspan: 1 }; }
Key Tips to Remember
- Sorting is mandatory: Make sure your data is sorted by
po_numberso all rows with the same Load Number are consecutive. Merging won't work correctly if matching Load Numbers are scattered. - Prop-based column targeting: Using
column.prop === 'product'instead of column index ensures the logic works even if you reorder your table columns later. - Custom sorting compatibility: Since you're using
sortable="custom", update your custom sort function to reprocessmergedTableDataafter sorting to maintain correct merging.
内容的提问来源于stack exchange,提问作者Xiaozhou Song

