VUE+elementUI动态tab切换表格,表头含动态下拉选择,表格含input提交表格信息

1,727 阅读2分钟

先来描述一下整个业务需求吧,文件上传时发送请求,跳转页面,如下图

由于表格内容过长分两部分来裁剪,看着页面很简单是吧,其实里面的逻辑很复杂,首先tab是根据后台传来的数据动态生成的,其次表头中嵌入动态下拉选择年份,先给大家看看后台返回的数据格式

我们针对于此处数据格式来做一个分析,tableData使我们所需要的table数据,里面每一项年份正是动态展示的年份,name如何将动态下拉放入表格来修改呢,此处认真看过elementui文档的同学就发现了有个 render-header 他后面可以跟一个回调,代码如下:

<el-table-column
      :render-header="(h) => renderHeaderA(h, index, item)"
      v-for="(item, index) in tableHeader"
      :key="index"
      :prop="item"
      align="center">
      <template slot-scope="scope">
        <el-input
          size="small"
          v-model="scope.row[item]"
          placeholder="请输入内容"
        ></el-input>
        <!-- <span>{{ item }}</span> -->
      </template>
</el-table-column>
renderHeaderA(h, index, prop) {
      let filters = [
        {
          text: "2016年",
          value: 2016,
        },
        {
          text: "2017年",
          value: 2017,
        },
        {
          text: "2018年",
          value: 2018,
        },
        {
          text: "2019年",
          value: 2019,
        },
        {
          text: "2020年",
          value: 2020,
        },
      ];
      return h("div", [
        h(
          "el-select",
          {
            class: "level-sel",
            on: {
              input: (value) => {
                this.$set(this.chooseHead, prop, value);
                this.tableHeader.forEach((item, index) => {
                  console.log(prop,item);
                  if (!!parseInt(prop) && prop === item) {
                  console.log(prop,item);
                    this.$set(this.tableHeader, index, value + "");
                    //这里用$set因为修改数据,数据改了试图没有修改
                    this.tableData.forEach(item => {
                      item[value] = item[prop]
                    })
                  }
                })
              },
            },
            props: {
              //文字框的内容取决于这个value,如果value不存在,会报错
              value: this.chooseHead[prop] || this.startStatus,
            },
          },
          [
            filters.map((item) => {
              return h("el-option", {
                props: {
                  value: item.value,
                  label: item.text,
                },
              });
            }),
          ]
        ),
      ]);
    },
  },
tableHeader: [], //这里是后台传来的年份  已做过处理
chooseHead: {
        2016: 2016,
        2017: 2017,
        2018: 2018,
        2019: 2019,
        2020: 2020,
      },  //这里是用户选择年份并回显

上面的三步我们仅仅只是把表格的th下拉选择做好了,接下来该展示tab切换时做的数据处理

  getTableData() {
      // 获取表格总数据
      this.currentTableData = sesstion.getLocalData("fileTableData");
      console.log(this.currentTableData);
      this.submitTableData = {...this.currentTableData};
      if (this.currentTableData.table_data["资产负债表"]) {
        this.tableTextList[0] = {
          name: "资产负债表",
          tableData:
            this.currentTableData.table_data["资产负债表"].tableData || [],
          listData:
            this.currentTableData.table_data["资产负债表"].listData || [],
        };
        this.yearData[0] = this.updateYearData(
          this.currentTableData.table_data["资产负债表"].tableData
        );
      }
      if (this.currentTableData.table_data["利润表"]) {
        this.tableTextList[1] = {
          name: "利润表",
          tableData: this.currentTableData.table_data["利润表"].tableData || [],
          listData: this.currentTableData.table_data["利润表"].listData || [],
        };
        this.yearData[1] = this.updateYearData(
          this.currentTableData.table_data["利润表"].tableData
        );
      }
      if (this.currentTableData.table_data["现金流量表"]) {
        this.tableTextList[2] = {
          name: "现金流量表",
          tableData:
            this.currentTableData.table_data["现金流量表"].tableData || [],
          listData:
            this.currentTableData.table_data["现金流量表"].listData || [],
        };
        this.yearData[2] = this.updateYearData(
          this.currentTableData.table_data["现金流量表"].tableData
        );
      }
	// 此处this.updateYearData是一个处理后台数据的方法,
       // 每一个表都要做相同的处理并且传给子组件

    },

最麻烦的应该就是处理数据了,我们要把查分开后端数据做显示的数据,在保存时给后台传送回去,刚才我们下拉选择年份时后台有可能传无法识别年份,对于无法识别的年份,前端展示“请选择”,但是这个时候chooseHead里面的数据已经被修改了,无法判断哪个年份是当时“无法识别”的年份,所以需要用原数据去跟修改后的数据作比较,并且将元数据的key替换成修改后的value,代码如下:

saveData() {
    
        console.log(this.$refs.table);
        console.log(this.chooseHead);
        console.log(this.tableData);
        console.log(this.tableLable);
        this.obj = {};
        this.obj.company_code = this.companyCode || "";
        this.obj.table_data = {
          [this.tableLable]: {
            tableData: { ...this.tableData },
          },
        };

        console.log(this.obj);

        var flage = true;

        this.tableData.forEach((v, i) => {
          for (let i1 in v) {
            // arr2 = Object.keys(i1)
            if (v[i1] == "") {
              flage = false;
              break;
            }
          }
          let that = this;
          let arr1 = Object.keys(that.chooseHead);
          let arr2 = Object.keys(v);

          arr2.forEach(function (item2) {
            // console.log(arr1);
            arr1.forEach((item1) => {
              if (item2 === item1) {
                v[that.chooseHead[item1] + "NY"] = parseInt(v[item2]) ? parseInt(v[item2]) : v[item2];
                //说明一下这里为什么要加NY,因为在前端对象中有key则是修改,没有则是添加因为要循环对比,所以需要加NY来区分
                // v[that.chooseHead[item1]] = v[item2];
                delete v[item1];
              }
            });
          });
          console.log(this.chooseHead);
        });
        console.log(this.tableData, this.tableLable);

        // let currentData = [...this.tableData]
        
        // this.tableData = JSON.parse(
        //   JSON.stringify(currentData).replace(/NY/g, "")
        // );
        this.obj = JSON.stringify(this.obj).replace(/NY/g, "");
        //这里是处理NY的代码

        let tableString = JSON.stringify(this.tableData).replace(/NY/g, "");
        // let tableString_data = JSON.stringify(this.tableData).replace(/NY/g, "");
        console.log(tableString, this.tableData);
        // this.tableData = JSON.parse(tableString_data);
        this.totalData = {
          tableLable: this.tableLable,
          tableData: tableString,
          tableHeader: this.tableHeader,
          index: this.index
        };
        if (!flage) {
          console.log("lalal");
          this.open();
        }
     
    },

看似好像完了,其实还没有结束,我们需要将拼接好的数据传回去,刚刚加了NY的年份需要再另一个页面去处理,将所有含NY的去掉,这样又引发了另一个问题,她点击保存后,这正个流程走了,但时用户又不想保存了,还想继续修改,所以整个流程按逻辑需要重新再走一遍,问题来了,没有保存意味着没有提交,没有提交意味着没有处理那个NY,就会发现我们修改了年份后,数据没了,写到这里时我已经崩溃了,但是问题还是要解决的,绞尽脑汁后,我想到了一个错误的方法-修改table值,经过不断的尝试不断地报错,发现没有遵循vue单向数据流(所以提醒大家vue基本不要忘记,否则错都不知道错在哪里),因为连表都是动态的,所以数据还得穿回来再做处理

getCurrentTableData(totalData) {
      // totalData  例 {tableLable: "资产负债表", tableData: ...}
      console.log(totalData, this.submitTableData);

      totalData.tableData = JSON.parse(totalData.tableData);

      // this.currentTableData.table_data[totalData.tableLable].tableData = totalData.tableData
      this.tableTextList[totalData.index].tableData = totalData.tableData
      // 回显 
      Object.keys(this.submitTableData.table_data).forEach(item => {
        if (this.submitTableData.table_data[item].listData) {
          this.submitTableData.table_data[item] = {tableData: this.submitTableData.table_data[item].tableData}
        }
      })
      
      this.submitTableData.table_data[totalData.tableLable] = {tableData: totalData.tableData}
    },