vue+element 在table中用jsx语法,列合并、列循环渲染

需求:
1.某些特定列需要合并
2.某几个列循环渲染
3.表格需要可点击行编辑单元格,
4.单元格需要行数据两值的对比来动态展示样式
因此用jsx能更好更快的解决

代码:

<template>
  <!-- 表格 -->
  <div class="table-page">
  <!-- span-method:el-table组件对列合并的事件-->
    <el-table
      class="table"
      ref="tablePage"
      v-bind="_attrs"
      v-loading="isLoading"
      element-loading-text="数据加载中,请稍候"
      element-loading-spinner="el-icon-loading"
      element-loading-background="rgba(255,255,255,0.8)"
      :span-method="arraySpanMethod"
    >
      <el-table-column fixed prop="prjDeptName" label="部门" width="150" align="center">
      </el-table-column>
      <el-table-column fixed prop="projectNumber" label="项目编号" width="220" align="center">
      </el-table-column>
      <el-table-column fixed prop="fundName" label="资金" width="150" align="center">
      </el-table-column>
      <el-table-column
        fixed
        prop="budgetForYear"
        :label="currentYear + '年预算金额'"
        width="150"
        align="center"
      >
      </el-table-column>
      <el-table-column
        fixed
        prop="budgetToLeave"
        :label="currentYear - 1 + '年结转金额'"
        width="150"
        align="center"
      >
      </el-table-column>
      <!-- 这里只能用template 用div或者别的标签会让循环前的列跑到最后 -->
      <template v-for="(month, index) in 10">
        <el-table-column :label="'1-' + [month + 2] + '月支出'" :key="month" align="center">
          <el-table-column :prop="planCountArr[index]" label="预计支出" width="120" align="center">
            <template slot-scope="scope">
              <!-- 数据为-1的置为空字符串 -->
              <span>{{
                scope.row[planCountArr[index]] == -1 ? '' : scope.row[planCountArr[index]]
              }}</span>
            </template>
          </el-table-column>
          <el-table-column
            :prop="realCountArrange[index]"
            label="实际支出"
            width="120"
            align="center"
            class-name="realCountStyle"
          >
            <template slot-scope="scope">
              <div
                :class="
                  cellColor(scope.row[planCountArr[index]], scope.row[realCountArrange[index]])
                "
              >
                <template v-if="canEdit">
                  {{ renderToInput(scope.row, index) }}
                  <!-- 这个slot必须要定义 不然render不生效,name要和table-cloumn的prop一致 -->
                  <slot :name="realCountArrange[index]"></slot>
                </template>
                <template v-else>
                  {{
                    scope.row[realCountArrange[index]] == -1
                      ? ''
                      : scope.row[realCountArrange[index]]
                  }}
                </template>
              </div>
            </template>
          </el-table-column>
        </el-table-column>
      </template>
      <el-table-column prop="remark" label="备注" width="150" align="center"> </el-table-column>
    </el-table>
  </div>
</template>
<script>
import { listProjectBudgetPayCount } from '@/api/budgetManagement' //接口
export default {
  name: 'excelPreview',
  props: {
    params: {
      type: Object,
      default: () => {}
    },
    //实际支出是否可编辑
    canEdit: {
      type: Boolean,
      default: false
    },
    //当前年
    currentYear: {
      type: String,
      default: String(new Date().getFullYear())
    }
  },
  data() {
    return {
      // 预计支出字段集
      planCountArr: [
        'payPlanJanMarCount',
        'payPlanJanAprCount',
        'payPlanJanMayCount',
        'payPlanJanJunCount',
        'payPlanJanJulCount',
        'payPlanJanAugCount',
        'payPlanJanSepCount',
        'payPlanJanOctCount',
        'payPlanJanNovCount',
        'payPlanJanDecCount'
      ],
      // 实际支出字段集
      realCountArrange: [
        'payRealJanMarCount',
        'payRealJanAprCount',
        'payRealJanMayCount',
        'payRealJanJunCount',
        'payRealJanJulCount',
        'payRealJanAugCount',
        'payRealJanSepCount',
        'payRealJanOctCount',
        'payRealJanNovCount',
        'payRealJanDecCount'
      ],
      isLoading: false,
      tableData: []
    }
  },
  computed: {
    _attrs() {
      return {
        data: this.tableData,
        stripe: false,
        border: true,
        height: 'calc(100% - 48px)'
      }
    }
  },
  mounted() {
    this.initData()
  },
  methods: {
    // 初始化数据
    async initData() {
      let res = await listProjectBudgetPayCount(this.params)
      this.tableData = res.data ?? []
    },
    // 合并列
    arraySpanMethod(data) {
      const { row, columnIndex } = data
      if (row.mergeCol) {
        if (columnIndex == 0) {
          // 第一列合并
          return [1, 3]
        } else if (columnIndex > 0 && columnIndex < 3) {
          // 合并的其他列不展示
          return [0, 0]
        }
      }
    },
    //单元格的样式
    cellColor(planCount, realCount) {
      if (planCount > realCount) {
        return 'countWarning'
      } else {
        return 'countNormal'
      }
    },
    //jsx语法
    renderToInput(row, index) {
    // 使用js动态新增一个slot实现render函数jsx语法渲染
      this.$slots[this.realCountArrange[index]] = (
        <div>
          {
            <el-input
              v-model={row[this.realCountArrange[index]]}
              placeholder="请输入"
              clearable
              vOn:class={this.cellColor(
                row[this.planCountArr[index]],
                row[this.realCountArrange[index]]
              )}
            ></el-input>
          }
        </div>
      )
    }
  }
}
</script>
<style lang="scss" scoped>
.table-page {
  position: relative;
  flex-grow: 1;
  margin-left: 24px;
  margin-right: 24px;
  .el-table {
    position: absolute;
    background-color: transparent;
  }
}
::v-deep .el-table__row .realCountStyle {
  padding: unset;
  .cell {
    padding: unset;
  }
}
.countWarning {
  display: inline-block;
  width: 100%;
  height: 100%;
  line-height: 47px;
  background-color: #ff4444;
  color: #fff;
  ::v-deep .el-input__inner {
    background-color: #ff4444;
    color: #fff;
  }
  // 清除按钮样式更改
  ::v-deep .el-input__suffix {
    .el-input__suffix-inner {
      border-color: none;
      .el-icon-circle-close:before {
        color: #fff;
      }
    }
  }
}
::v-deep {
  .el-table__body-wrapper {
    @include scrollBar;
  }
  // 解决固定列后滚动条无效的问题
  .el-table__fixed {
    height: auto !important;
    bottom: 12px;
  }
  .el-input__inner {
    padding: 0 15px !important;
    text-align: center;
    border: unset;
    &::placeholder {
      color: #fff;
    }
  }
}
</style>

你可能感兴趣的:(vue.js,javascript,前端)