美文网首页让前端飞前端开发记录web前端技术分享
element ui 表格动态列,单行合并同时可行内编辑

element ui 表格动态列,单行合并同时可行内编辑

作者: 阿巳交不起水电费 | 来源:发表于2022-11-17 15:08 被阅读0次

    效果如下:


    image.png
    image.png

    版本信息如下:

    "vue": "^2.5.2", "element-ui": "^2.7.2",

    代码如下:

    <!--表格行合并-->
    <template>
      <div style="margin: 20px">
        <div style="margin: 20px 0;text-align: right;">
          <el-button type="primary" @click="logTableData">打印表格数据</el-button>
        </div>
        <el-table
          v-loading="tableLoading"
          :data="tableData"
          :span-method="spanMethod"
          :header-row-style="headerRowStyle"
          style="width: 100%">
    
          <el-table-column
            align="center"
            v-for="(col,colIndex) in tableHeader"
            :key="`col-${colIndex}`"
            :prop="col.prop"
            :min-width="col.width || 80"
            :label="col.label">
            <template slot-scope="{row, $index}">
              <el-input v-if="!col.noEdit && row._edit" class="inputNumber" :placeholder="`请输入${col.label}`"
                        v-model="row[col.prop]"/>
              <span v-else>{{ row[col.prop] }}</span>
            </template>
          </el-table-column>
    
          <el-table-column align="center" label="配比">
            <el-table-column label="" align="center" v-for="rateColIndex in maxTableColLength" :key="`rate-${rateColIndex}`"
                             :min-width="80">
              <template slot-scope="{row, $index}">
    
    
                <!--                第一行-->
                <template v-if="row.rowSpan">
                  <span v-if="rateColIndex <= row.list.length">{{ row.list[rateColIndex - 1].name }}</span>
                </template>
    
                <!--                第二行,操作的也是上一行的数据-->
                <!--              有这项的才可编辑-->
                <template v-else-if="rateColIndex <= tableData[$index-1].list.length">
    
                  <el-input class="inputNumber" type="number" v-if="tableData[$index-1]._edit" placeholder="请输入"
                            v-model="tableData[$index-1].list[rateColIndex-1].rate"/>
                  <span v-else>{{ valFixed(tableData[$index-1].list[rateColIndex - 1].rate, 2) }}</span>
    
                </template>
    
              </template>
            </el-table-column>
          </el-table-column>
    
          <el-table-column
            fixed="right"
            align="center"
            label="操作"
            width="120">
            <template slot-scope="{row,$index}">
              <template v-if="!row._edit">
                <el-button @click="rowEdit(row, $index)" type="text">修改</el-button>
              </template>
              <template v-else>
                <el-button @click="rowSave(row, $index)" type="text">保存</el-button>
                <el-button @click="rowCancel(row, $index)" type="text">取消</el-button>
              </template>
            </template>
          </el-table-column>
        </el-table>
      </div>
    </template>
    
    <script>
    export default {
      data() {
        return {
          tableLoading: false,
          tableHeader: [
            {
              prop: 'pileNo',
              label: '堆号',
              noEdit: true
            },
            {
              prop: 'tfe',
              label: '品位'
            },
            {
              prop: 'ironWeight',
              label: '铁水产量'
            }
          ],
          tableData: [],
          historyRow: null, // 行编辑时存储历史数据
        }
      },
      computed: {
        // 表格中最大配比列长度
        maxTableColLength() {
          let arr = this.tableData.map(item => {
            return (item.list || []).length
          })
          return arr.length ? Math.max(...arr) : 0
        },
      },
      created() {
        this.initData()
      },
      methods: {
        // 判断值是否为空
        isNull(val) {
          return val === null || val === void 0 || val === '' || (val).toString() === 'NaN'
        },
        /**
         * 值保留小数处理
         * @val: 需要保留小数的值
         * @fixed:小数位数
         * @dt:为空时的默认值
         * @unit:单位
         * */
        valFixed(val, fixed = 3, dt = '', unit = '') {
          return this.isNull(val) ? dt : (parseFloat(val).toFixed(fixed) + unit)
        },
        initData() {
          // 模拟数据
          let data = [
            {
              pileNo: '11111111',
              tfe: 56.2,
              ironWeight: 5000,
              list: [
                {
                  name: '精粉1',
                  rate: 10,
                },
                {
                  name: '精粉2',
                  rate: 5,
                },
                {
                  name: '混合粉2',
                  rate: 8,
                },
                {
                  name: '混合粉4',
                  rate: 3,
                }
              ],
            },
            {
              pileNo: '22222222',
              tfe: 50.34,
              ironWeight: 5500,
              list: [
                {
                  name: '精粉5',
                  rate: 10,
                },
                {
                  name: '混合粉1',
                  rate: 8,
                },
                {
                  name: '混合粉2',
                  rate: 3,
                }
              ],
            },
            {
              pileNo: '33333333',
              tfe: 49,
              ironWeight: 4900,
              list: [
                {
                  name: '精粉5',
                  rate: 5,
                },
                {
                  name: '混合粉1',
                  rate: 10,
                },
                {
                  name: '混合粉2',
                  rate: 20,
                },
                {
                  name: '混合粉3',
                  rate: 20,
                }
              ],
            }
          ]
    
          let tableData = []
          data.map(item => {
            let list = item.list || []
            tableData = tableData.concat([
              {
                ...item,
                // 辅助变量
                rowSpan: 2
              },
              {}
            ])
          })
          this.tableData = tableData
        },
    
        // 表头隐藏
        headerRowStyle({row, rowIndex}) {
          if (rowIndex === 1) {
            return {'display': 'none'}
          }
        },
        // 表格行合并
        spanMethod({row, column, rowIndex, columnIndex}) {
          let startColIndex = this.tableHeader.length // 数的,第五列开始是配比列
          let endColIndex = startColIndex + (this.maxTableColLength - 1)
          let isRateCol = columnIndex >= startColIndex && columnIndex <= endColIndex // 配比列不进行行合并
          if (row.rowSpan) { // name行
            if (!isRateCol) {
              return [row.rowSpan, 1]
            } else {
              return [1, 1]
            }
          } else { // 配比行
            if (!isRateCol) {
              return [0, 1]
            } else {
              return [1, 1]
            }
          }
    
        },
    
        // 打印数据
        logTableData() {
          let data = this.tableData.filter(item => item.rowSpan)
          data.map((item) => {
            let str = ''
            this.tableHeader.map(sub => {
              str += `${sub.label}: ${item[sub.prop]} `
            })
            item.list.map(sub => {
              str += `${sub.name}: ${sub.rate} `
            })
            console.log(`%c${str}`, 'color: #43bb88;font-weight: bold;');
          })
    
          console.log('最终数据为:', data)
        },
    
        // 行编辑 --------------- start
    
        // 修改
        rowEdit(row, rowIndex) {
          // console.log(row, rowIndex)
          if (this.tableData.find(item => item._edit)) return this.$message({
            message: '请保存正在编辑的行',
            type: 'warning'
          });
    
          let editRow = row
          this.historyRow = JSON.parse(JSON.stringify(editRow))
          this.$set(editRow, '_edit', true)
        },
        // 保存正在编辑的
        rowSave(row, rowIndex) {
          // console.log(row, rowIndex)
          this.historyRow = {}
          row._edit = false
        },
        // 取消保存
        rowCancel(row, rowIndex) {
          // console.log(row, rowIndex)
          this.tableData.splice(rowIndex, 1, {
            ...this.historyRow,
            _edit: false
          })
          this.historyRow = {}
        }
    
        // 行编辑 --------------- end
      }
    }
    </script>
    
    <style scoped lang="less">
    
    .inputNumber {
      /deep/ input::-webkit-outer-spin-button,
      /deep/ input::-webkit-inner-spin-button {
        -webkit-appearance: none !important;
      }
    
      /deep/ input[type='number'] {
        -moz-appearance: textfield;
      }
    }
    </style>
    
    

    大体思路

    image.png

    1.表头其实有两行,下面这行被隐藏了。
    2.表格中每行数据是两行,表格行合并了,第二行是空行,编辑时操作的是第一行的数据。
    3.这里使用行合并是为了让配比列表格宽度自适应。

    若对你有帮助,请点个赞吧,谢谢支持!
    本文地址:https://www.jianshu.com/p/0fdfbb68a73e?v=1668668903593,转载请注明出处,谢谢。

    相关文章

      网友评论

        本文标题:element ui 表格动态列,单行合并同时可行内编辑

        本文链接:https://www.haomeiwen.com/subject/sgsptdtx.html