Element UI el-table form 表单的封装思路

Element UI el-table form 表单的封装思路

思路一: 将所有 form 表单类型都在 el-column-item 组件中定义好,然后根据传入的属性控制展示哪一个 form 表单类型

部分代码如下:

<template>
  <div>
    <el-row style="padding: 0 20px">
      <el-col :span="24" style="text-align: right">
        <el-button @click.native="addRow" v-if="!isOperated"
          ><i class="el-icon-plus el-icon--left"></i>新增行</el-button
        >
      </el-col>
    </el-row>
    <el-row style="padding: 20px">
      <el-table
        ref="multipleTable"
        stripe
        border
        height="250"
        :data="data"
        tooltip-effect="dark"
        style="width: 100%"
      >
        <el-table-column
          type="index"
          label="序号"
          width="50"
          align="center"
          fixed="left"
        >
        </el-table-column>
        <template v-for="(v, i) in modulsList">
          <el-table-column
            v-if="!v.hidden"
            :label="v.label"
            :prop="v.prop"
            :key="i"
            :width="v.width"
            align="center"
          >
            <template slot-scope="scope">
              <el-form-item
                :prop="
                  dataTag ? `${
      
      dataTag}.${
      
      scope.$index}.${
      
      v.prop}` : v.prop
                "
                label-width="15px"
                label=" "
                :rules="v.rules"
              >
                <template v-if="v.type === 'text'">
                  <el-input
                    type="text"
                    v-model="scope.row[v.prop]"
                    :disabled="v.disabled"
                  ></el-input>
                </template>
                <template v-else-if="v.type === 'number'">
                  <el-input-number
                    v-model="scope.row[v.prop]"
                    :min="0"
                  ></el-input-number>
                </template>
                <template v-else-if="v.type === 'textarea'">
                  <el-input
                    type="textarea"
                    :maxlength="v.maxlength"
                    :show-word-limit="v.limit"
                    v-model="scope.row[v.prop]"
                    :disabled="v.disabled"
                  ></el-input>
                </template>
                <template v-else-if="v.type === 'datePicker'">
                  <el-date-picker
                    v-model="scope.row[v.prop]"
                    type="date"
                    placeholder="选择日期"
                    value-format="timestamp"
                    :disabled="v.disabled"
                  >
                  </el-date-picker>
                </template>
                <template v-else-if="v.type === 'select'">
                  <el-select v-model="scope.row[v.prop]" placeholder="请选择">
                    <template v-for="(x, j) in v.options">
                      <el-option
                        :label="x.label"
                        :value="x.value"
                        :key="j"
                      ></el-option>
                    </template>
                  </el-select>
                </template>
                <template v-else-if="v.type === 'switch'">
                  <el-switch v-model="scope.row[v.prop]"></el-switch>
                </template>
                <template v-else-if="v.type === 'selectRemote'">
                  <el-select
                    v-model="scope.row[v.prop]"
                    filterable
                    remote
                    placeholder="请输入"
                    :remote-method="v.searchMethod"
                    @change="v.changeMethod"
                  >
                    <el-option
                      v-for="(item, i) in v.selectOption"
                      :key="i"
                      :label="item.label"
                      :value="item.value"
                    ></el-option>
                  </el-select>
                </template>
                <template v-else> </template>
              </el-form-item>
            </template>
          </el-table-column>
        </template>
        <el-table-column
          label="操作"
          width="100"
          align="center"
          fixed="right"
          v-if="!isOperated"
        >
          <template slot-scope="scope">
            <el-button type="text" size="mini" @click="deleteRow(scope.$index)">
              删除
            </el-button>
          </template>
        </el-table-column>
      </el-table>
    </el-row>
  </div>
</template>
<script>
export default {
    
    
  components: {
    
    },
  props: {
    
    
    // 展示模块
    // #description label:名称、prop:Data的对应字段、,type:类型 , default: 新增行默认值
    modulsList: {
    
    
      type: Array,
      default: () => {
    
    }
    },
    // 渲染数据
    data: {
    
    
      type: Array,
      default: () => []
    },
    // 校验标签头
    dataTag: {
    
    
      type: String,
      default: ''
    },
    isOperated: Boolean
  },
  data() {
    
    
    return {
    
    }
  },
  methods: {
    
    
    // 新增行
    addRow() {
    
    
      let addIndex = this.data.length
      let newArr = {
    
    }
      this.modulsList.forEach((v) => {
    
    
        newArr[v.prop] = v.default
      })
      this.$set(this.data, addIndex, newArr)
      console.log('新增行', this.data)
    },
    // 删除行
    deleteRow(index) {
    
    
      if (this.data.length <= 1) {
    
    
        this.$message.error('至少含有一条')
        return false
      }
      this.data.splice(index, 1)
      console.log('删除行', this.data)
    }
  },
  mounted() {
    
    
    // 至少含有一条
    if (this.data.length === 0) {
    
    
      this.addRow()
    }
  }
}
</script>
<style lang="scss" scoped>
.el-table > .el-input,
.el-textarea,
.el-select,
.el-date-editor,
.el-input-number {
    
    
  width: 100%;
}
</style>

思路二: 将所有 form 表单都单独封装,然后通过一个 js 文件 defineAsyncComponent 汇总这些单独封装的表单组件.使用的时候,通过 component is 来引入使用.

效果如下:
在这里插入图片描述

部分代码如下

汇总表单组件的 js文件代码:
import {
    
     defineAsyncComponent } from 'vue'
const formMap = {
    
    
  FInput: defineAsyncComponent(() =>
    import('@/components/form/items/fInput.vue')
  ),

  FRadio: defineAsyncComponent(() =>
    import('@/components/form/items/fRadio.vue')
  ),
  FSwitch: defineAsyncComponent(() =>
    import('@/components/form/items/fSwitch.vue')
  ),
  FSelect: defineAsyncComponent(() =>
    import('@/components/form/items/fSelect.vue')
  ),
  FCheckbox: defineAsyncComponent(() =>
    import('@/components/form/items/fCheckbox.vue')
  ),
  FDateTimePicker: defineAsyncComponent(() =>
    import('@/components/form/items/fDateTimePicker.vue')
  ),
  FSelectUser: defineAsyncComponent(() =>
    import('@/components/form/items/fSelectUser.vue')
  ),
  FPartNo: defineAsyncComponent(() =>
    import('@/components/form/items/fPartNo.vue')
  ),
  FSelectSupplier: defineAsyncComponent(() =>
    import('@/components/form/items/fSelectSupplier.vue')
  ),
  FSupplierMaster: defineAsyncComponent(() =>
    import('@/components/form/items/fSupplierMaster.vue')
  ),
  FCascader: defineAsyncComponent(() =>
    import('@/components/form/items/fCascader.vue')
  )
}

export default formMap


封装的 formTable 组件代码如下:
<template>
  <div class="formTable">
    <el-table :data="formTableList.tableData" border style="width: 100%">
      <el-table-column
        v-for="(item, index) in formTableList.tableHeader"
        :key="index"
        :prop="item.prop"
        :label="item.label"
        align="center"
      >
        <template slot-scope="scope">
          <span v-if="item.isTitle"> {
    
    {
    
     scope.row[item.prop] }}</span>
          <el-form
            v-if="!item.isTitle"
            ref="refForm"
            :model="scope.row"
            :rules="formTableList.formRules"
            :label-width="labelWidth"
            class="demo-form-inline"
          >
            <el-form-item :prop="item.prop" label=" ">
              <component
                :is="formMap[item.formType]"
                :meta="item.meta"
                :obj="scope.row"
              ></component>
            </el-form-item>
          </el-form>
        </template>
      </el-table-column>
    </el-table>
  </div>
</template>

<script>
import formMap from '@/components/form/formMap.js'
export default {
    
    
  name: 'FormTable',
  //   watch: {
    
    
  //     formTableList: {
    
    
  //       deep: true,
  //       handler(val) {
    
    
  //         console.log(val)
  //       }
  //     }
  //   },
  props: {
    
    
    formTableList: {
    
    
      type: Object,
      default() {
    
    
        return {
    
    }
      }
    },
    labelWidth: {
    
    
      type: String,
      default: 'auto'
    }
  },
  data() {
    
    
    return {
    
    
      formMap
    }
  },
  methods: {
    
    
    modelRef() {
    
    
      return this.$refs.refForm
    }
  }
}
</script>

<style lang="scss" scoped>
.formTable {
    
    
  padding-bottom: 20px;
}
::v-deep .el-select {
    
    
  width: 100%;
}
</style>

使用 formTable 组件配置项代码如下:

<FormTable
  ref="partFourModelRef"
  :formTableList="formTableList"
></FormTable>

      formTableList: {
    
    
        formRules: {
    
    
          RPN: [{
    
     required: true, message: '请输入', trigger: ['blur'] }],
          yanzhongdu: [
            {
    
     required: true, message: '请输入', trigger: ['blur'] }
          ],
          pindu: [{
    
     required: true, message: '请输入', trigger: ['blur'] }],
          tancedu: [{
    
     required: true, message: '请输入', trigger: ['blur'] }]
        },
        tableHeader: [
          {
    
    
            prop: 'fangmian',
            label: '方面',
            isTitle: true,
            meta: {
    
    
              fProp: 'fangmian'
            }
          },
          {
    
    
            prop: 'RPN',
            label: 'RPN',
            formType: 'FInput',
            meta: {
    
    
              fProp: 'RPN'
            }
          },
          {
    
    
            prop: 'yanzhongdu',
            label: '严重度(S)',
            formType: 'FInput',
            meta: {
    
    
              fProp: 'yanzhongdu'
            }
          },
          {
    
    
            prop: 'pindu',
            label: '频度(O)',
            formType: 'FInput',
            meta: {
    
    
              fProp: 'pindu'
            }
          },
          {
    
    
            prop: 'tancedu',
            label: '探测度(D)',
            formType: 'FInput',
            meta: {
    
    
              fProp: 'tancedu'
            }
          }
        ],
        tableData: [
          {
    
    
            fangmian: '改善前'
          },
          {
    
    
            fangmian: '改善后'
          }
        ]
      }

猜你喜欢

转载自blog.csdn.net/i_Satan/article/details/130982628