vue element-ui自定义表头,动态添加表头,新增行、新增列、删除行、删除列

  • Post author:
  • Post category:vue




需求描述

根据项目需求,需要用户填写几行几列,表头自定义动态添加,用户可以手动新增行、新增列、删除行、删除列,怎么实现一起来看看吧~



1.自定义表头,表头里插入输入框

<el-form ref="historyForm" :model="historyForm" size="small">
  <div class="table-box" @contextmenu.prevent.capture>
    <el-table
      :data="historyForm.tableData"
      :loading="loading"
      style="width: 100%"
      class="list-table default-scrollbar"
      size="mini"
      @header-contextmenu="rightClickColShowFun"
      @row-contextmenu="rightClickRowShowFun"
      :cell-class-name="tableClassName"
      border>
      <el-table-column label="序号" align="center" width="50">
        <template slot-scope="scope">
          {{scope.$index+1}}
        </template>
      </el-table-column>
      <el-table-column label="等位基因" align="center" prop="name" class-name="cellDefault">
        <template slot-scope="scope">
          <el-input v-model="scope.row.name" class="name-input"></el-input>
        </template>
      </el-table-column>
      <el-table-column :label="'ABO-'+`${colList.length}`+'位点'" class-name="specital-title">
        <el-table-column align="center" class-name="cellDefault" v-for="(item,index) in colList" :key="index" min-width="40">
          <template #header>
            <el-input v-model="colList[index]" size="mini" @change="setColName(index,colList[index])"/>
          </template>
          <template slot-scope="scope">
            <el-input type="number" v-model.number="scope.row[item].value" @input="setInputVal" :class="scope.row[item].checked ? 'red' : ''"></el-input>
          </template>
        </el-table-column>
      </el-table-column>
    </el-table>
    <div class="add-column" @click="addColSetting">+</div>
  </div>
  <div class="add-line" @click="addParamsSetting">+</div>
</el-form>
data() {
  return {
    // 遮罩层
    loading: true,
    // 表单参数-表格内容数据
    historyForm: {
      tableData: []
    },
    // 表头列表数组
    colList: [],
    isAddCol: true,
    colNum: 0,
    rowNum: 0,
    currentId: null,
    mouldName: "A101templete",
    dialogRowVisible: false,// 新增行
    dialogColVisible: false,// 新增列
    currentClickRow: null,
    currentClickCol: null,
    resultList: [],
  };
},


特别注意:

添加 #header 才能自定义插入表头,否则会出现input框不能进行输入的Bug。



2.默认初始化几行几列占位

例如当前为3行4列占位,效果如下图展示。

在这里插入图片描述

methods: {
  // 根据默认几行几列初始化表格
  init() {
    for (let i = 0; i < this.colNum; i++) {
      this.colList.push("");
    }
    for (let j = 0; j < this.rowNum; j++) {
      if (j === 0) {
        this.historyForm.tableData.push({
          name: this.mouldName,
          "": {
            value: null,
            checked: 0
          }
        });
      }else {
        this.historyForm.tableData.push({
          name: null,
          "": {
            value: null,
            checked: 0
          }
        });
      }

    }
  },
}



3.新增行

// 新增行
methods: {
  // 在数组最后添加一行
  addParamsSetting () {
    this.addList()
  },
  addList () {
    let item = {
      name: null,
    };
    for (let i in this.colList) {
      item[this.colList[i]] = {
        value: null,
        checked: 0
      }
    }
    this.historyForm.tableData.push(item);
  },
}



4.新增列

methods: {
  // 在数据最后新增一列
  addColSetting() {
    for (let i in this.colList) {
      if (this.colList[i] === "") {
        this.isAddCol = false;
      }else {
        this.isAddCol = true;
      }
    }
    if (this.isAddCol) {
      this.addColList();
    }else {
      this.$message.success("还有未填写的列");
    }
  },
  // 新增列
  addColList() {
    let list = this.historyForm.tableData;
    for (let i = 0; i < list.length; i++) {
      list[i][""] = {
        value: null,
        checked: 0
      };
    }
    this.colList.push("");
  },
}


注意事项:

因为表头是自定义输入框动态添加的,所以需要限制用户先把表头填写完成,再进行填写单元格的内容,新添加列也同理,否则会出现数据重复的Bug。



5.右键点击行,进行删除行

想要删除行,首先要拿到rowIndex,我们可以利用:cell-class-name=“tableClassName”,拿到rowIndex,赋值给row,@row-contextmenu=“rightClickRowShowFun”,即可拿到行的索引,进行删除行操作。

methods: {
  // 给数据的row、column赋index,便于进行删除行、删除列
  tableClassName({row, column, rowIndex, columnIndex}) {
    row.index = rowIndex;
    column.index  = columnIndex - 2;
    if(rowIndex === 0){
      return 'blue'
    }
  },
  // 右键单击选中行-确认是否删除行
  rightClickRowShowFun(row) {
    this.currentClickRow = row.index;
    this.dialogRowVisible = true;
  },
  // 确认删除行
  submitFunRow() {
    this.dialogRowVisible = false;
    this.deleteRow(this.currentClickRow);
  },
  // 删除当前行
  deleteRow (index) {
    this.historyForm.tableData.splice(index, 1)
  },
}



6.右键点击表头,进行删除列

想要删除列,首先要拿到columnIndex,我们可以利用:cell-class-name=“tableClassName”,拿到columnIndex,赋值给column,@header-contextmenu=“rightClickColShowFun”,即可拿到列的索引,进行删除列操作。

methods: {
  // 给数据的row、column赋index,便于进行删除行、删除列
  tableClassName({row, column, rowIndex, columnIndex}) {
    row.index = rowIndex;
    column.index  = columnIndex - 2;
    if(rowIndex === 0){
      return 'blue'
    }
  },
  // 右键单击选中行-确认是否删除列
  rightClickColShowFun(column, event) {
    this.currentClickCol = column.index;
    this.dialogColVisible = true;
  },
  // 确认删除列
  submitFunCol() {
    this.dialogColVisible = false;
    this.deleteCol(this.currentClickCol);
  },
  // 删除当前列
  deleteCol (index) {
    this.colList.splice(index, 1)
  },
}



7.效果展示

在这里插入图片描述

单元格和表头内都插入的是输入框,写css样式可以进行修改输入框样式,我这里给单元格内的输入框限制了number类型(v-model.number),会出现上下增加数值的按钮,我给隐藏掉了,代码如下:

.cellDefault{
    padding: 0!important;
    .cell{
      padding: 0!important;
      input{
        border: none;
        border-radius: 0;
        text-align: center;
        background: #EEF8FF;
        padding: 0;
      }
      input::-webkit-outer-spin-button,
      input::-webkit-inner-spin-button {
        -webkit-appearance: none !important;
        margin: 0;
      }
    }
  }



8.所有代码总结

<template>
  <div class="app-container haplotype-detail default-scrollbar">
    <div>
      <el-form ref="historyForm" :model="historyForm" size="small">
        <div class="table-box" @contextmenu.prevent.capture>
          <el-table
            :data="historyForm.tableData"
            :loading="loading"
            style="width: 100%"
            class="list-table default-scrollbar"
            size="mini"
            @header-contextmenu="rightClickColShowFun"
            @row-contextmenu="rightClickRowShowFun"
            :cell-class-name="tableClassName"
            border>
            <el-table-column label="序号" align="center" width="50">
              <template slot-scope="scope">
                {{scope.$index+1}}
              </template>
            </el-table-column>
            <el-table-column label="等位基因" align="center" prop="name" class-name="cellDefault">
              <template slot-scope="scope">
                <el-input v-model="scope.row.name" class="name-input"></el-input>
              </template>
            </el-table-column>
            <el-table-column :label="'ABO-'+`${colList.length}`+'位点'" class-name="specital-title">
              <el-table-column align="center" class-name="cellDefault" v-for="(item,index) in colList" :key="index" min-width="40">
                <template #header>
                  <el-input v-model="colList[index]" size="mini" @change="setColName(index,colList[index])"/>
                </template>
                <template slot-scope="scope">
                  <el-input type="number" v-model.number="scope.row[item].value" @input="setInputVal" :class="scope.row[item].checked ? 'red' : ''"></el-input>
                </template>
              </el-table-column>
            </el-table-column>
          </el-table>
          <div class="add-column" @click="addColSetting">+</div>
        </div>
        <div class="add-line" @click="addParamsSetting">+</div>
        <div class="start-btn-box">
          <el-button type="primary" @click="startComparisonFun" class="start-btn">开始对比</el-button>
        </div>
      </el-form>
    </div>

    <el-dialog
      title="温馨提示"
      :visible.sync="dialogRowVisible"
      width="250px"
    >
      <span>确定删除此行数据嘛?</span>
      <div slot="footer" class="dialog-footer">
        <el-button @click="dialogRowVisible = false">取 消</el-button>
        <el-button type="primary" @click="submitFunRow">确 定</el-button>
      </div>
    </el-dialog>
    <el-dialog
      title="温馨提示"
      :visible.sync="dialogColVisible"
      width="250px"
    >
      <span>确定删除此列数据嘛?</span>
      <div slot="footer" class="dialog-footer">
        <el-button @click="dialogColVisible = false">取 消</el-button>
        <el-button type="primary" @click="submitFunCol">确 定</el-button>
      </div>
    </el-dialog>
  </div>
</template>
<script>
export default {
  name: "haplotypeDetail",
  data() {
    return {
      // 遮罩层
      loading: true,
      // 表单参数-表格内容数据
      historyForm: {
        tableData: []
      },
      // 表头列表数组
      colList: [],
      isAddCol: true,
      colNum: 0,
      rowNum: 0,
      currentId: null,
      mouldName: "A101templete",
      dialogRowVisible: false,// 新增行
      dialogColVisible: false,// 新增列
      currentClickRow: null,
      currentClickCol: null,
      resultList: [],
    };
  },
  methods: {
    // 根据默认几行几列初始化表格
    init() {
      for (let i = 0; i < this.colNum; i++) {
        this.colList.push("");
      }
      for (let j = 0; j < this.rowNum; j++) {
        if (j === 0) {
          this.historyForm.tableData.push({
            name: this.mouldName,
            "": {
              value: null,
              checked: 0
            }
          });
        }else {
          this.historyForm.tableData.push({
            name: null,
            "": {
              value: null,
              checked: 0
            }
          });
        }

      }
    },
    // 在数组最后添加一行
    addParamsSetting () {
      this.addList()
    },
    // 新增行
    addList () {
      let item = {
        name: null,
      };
      for (let i in this.colList) {
        item[this.colList[i]] = {
          value: null,
          checked: 0
        }
      }
      this.historyForm.tableData.push(item);
    },
    // 删除当前行
    deleteRow (index) {
      this.historyForm.tableData.splice(index, 1)
    },
    // 在数据最后新增一列
    addColSetting() {
      for (let i in this.colList) {
        if (this.colList[i] === "") {
          this.isAddCol = false;
        }else {
          this.isAddCol = true;
        }
      }
      if (this.isAddCol) {
        this.addColList();
      }else {
        this.$message.success("还有未填写的列");
      }
    },
    // 新增列
    addColList() {
      let list = this.historyForm.tableData;
      for (let i = 0; i < list.length; i++) {
        list[i][""] = {
          value: null,
          checked: 0
        };
      }
      this.colList.push("");
    },
    // 修改表头名fun
    setColName(index, val) {
      let list = this.historyForm.tableData;
      for (let i = 0; i < list.length; i++) {
        this.$set(list[i],val,{
          value: null,
          checked: 0
        })
      }
      this.$forceUpdate();
    },
    // 输入内容数据的fun
    setInputVal() {
      for (let i in this.colList) {
        if (this.colList[i] === "") {
          this.isAddCol = false;
        }else {
          this.isAddCol = true;
        }
      }
      if (!this.isAddCol) {
        this.$message.success("请先填写完成所有表头内容,且确保无误!");
        let list = this.historyForm.tableData;
        for (let j = 0; j < list.length; j++) {
          if (list[j][""]) {
            list[j][""] = {
              value: null,
              checked: 0
            };
          }
        }
      }
    },
    // 右键单击选中行-确认是否删除行
    rightClickRowShowFun(row, column, event) {
      this.currentClickRow = row.index;
      this.dialogRowVisible = true;
    },
    // 右键单击选中行-确认是否删除列
    rightClickColShowFun(column, event) {
      this.currentClickCol = column.index;
      this.dialogColVisible = true;
    },
    // 确认删除行
    submitFunRow() {
      this.dialogRowVisible = false;
      this.deleteRow(this.currentClickRow);
    },
    // 给数据的row、column赋index,便于进行删除行、删除列
    tableClassName({row, column, rowIndex, columnIndex}) {
      row.index = rowIndex;
      column.index  = columnIndex - 2;
      if(rowIndex === 0){
        return 'blue'
      }
    },
    // 确认删除列
    submitFunCol() {
      this.dialogColVisible = false;
      this.deleteCol(this.currentClickCol);
    },
    // 删除当前列
    deleteCol (index) {
      this.colList.splice(index, 1)
    },
  },
}
</script>
<style lang="scss">
.haplotype-detail{
  .list-table{
    background: #EEF8FF;
    &.el-table thead.is-group th.el-table__cell{
      background: #EEF8FF;
    }
    &.el-table td.el-table__cell{
      background: #EEF8FF;
      color: #0083D7;
    }
    .name-input{
      input{
        color: #0083D7;
      }
    }
    .specital-title{
      color: #0083D7;
      font-size: 16px;
      font-family: Source Han Sans CN;
      font-weight: bold;
    }
  }
  .el-table--enable-row-hover .el-table__body tr:hover > td.el-table__cell{
    background: #A0D8FF;
    .cell input{
      background: #A0D8FF;
    }
  }
  .cellDefault{
    padding: 0!important;
    .cell{
      padding: 0!important;
      input{
        border: none;
        border-radius: 0;
        text-align: center;
        background: #EEF8FF;
        padding: 0;
      }
      input::-webkit-outer-spin-button,
      input::-webkit-inner-spin-button {
        -webkit-appearance: none !important;
        margin: 0;
      }
    }
  }
  th.cellDefault{
    input{
      background: #F5F7FA;
    }
  }
  .red{
    background: #E8CCCB;
    input{
      background: #E8CCCB!important;
      color: #DD262F;
    }
  }
  .blue{
    background: #A0D8FF!important;
    input{
      background: #A0D8FF!important;
    }
  }
}



版权声明:本文为ALSO666原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。