vue + element-ui 中 el-table 动态生成表头及有必填项

本文详细介绍了在Vue项目中如何实现动态表头,包括新增、编辑、删除和隐藏表头功能,并展示了针对不同数据类型的输入组件,如String、Numeric、Date和List。在List类型中,使用el-select并关联数据。同时,文章提到了数值类型输入的正则校验以及必填项的判断。最后,展示了实现效果和总结了整个过程。
摘要由CSDN通过智能技术生成

实现效果:

需求描述 : 

A模块
B模块
  • 用户可在 “A模块” 中新增、编辑、删除、隐藏表头项。
  • 在 “B模块” 中动态显示用户设置好的表头。
  • 表头下数据类型有StringNumeric、Date、List四种类型。
  • 类型为 String、Numeric、Date 时为 input 格式。
  • 类型为 List 时为 el-select 格式。
  • 类型为 List 时 el-select 内数据由用户在新增时与规定模块进行关联选择。

 实现方法:

思路:

  • 根据后端接口返回数据实现动态表头
  • 后台接口可为 “A模块” 中的查询全部列表的接口,也可以是后端新写的接口(推荐)。

 代码:

html中:

<el-row class="tab back-gauge">
        <el-table ref="tab" :data="tableData" border class="tab-table" style="width: 100%" :header-cell-style="{background:'#1890FF', color:'#FFF' }" :empty-text="$t('assets.text')">
          <!-- 动态表头 -->
          <el-table-column
            v-for="(item, index) in attributeData"
            :key="index"
            :render-header="(h,obj) => addRedStar(h, obj, item.isWrited)"
            :label="item.name"
            :prop="item.code"
            show-overflow-tooltip
            align="center"
          >
            <template slot-scope="scope">
              <el-input v-if="item.type === '字符型'" v-model="scope.row[scope.column.property]" placeholder="请输入字符" />
              <el-date-picker
                v-if="item.type === '日期型'"
                v-model="scope.row[scope.column.property]"
                type="date"
                placeholder="选择日期"
                format="yyyy-MM-dd"
                value-format="yyyy-MM-dd"
              />
              <!-- </el-input> -->
              <el-input
                v-if="item.type === '数值型'"
                :id="'NumInput' + index + scope.$index"
                v-model="scope.row[scope.column.property]"
                placeholder="请输入数值"
                oninput="value=value.replace(/[^\d]/g,'')"
                @input="NumInput(index, scope.$index)"
              />
              <el-select
                v-if="item.type === '列表型'"
                :ref="item.code + scope.$index"
                v-model="tableData[scope.$index][item.code]"
                :placeholder="item.index"
                clearable
                @visible-change="changeValueCategory($event, scope.$index, index)"
              >
                <el-option :value="tableData[scope.$index][item.code]" style="height: auto">
                  <el-tree
                    :ref="item.code +'Tree' + scope.$index"
                    :data="dynamicData[item.code]"
                    node-key="id"
                    :props="typeTreeProps"
                    @node-click="getTypeList(scope.$index, index)"
                  >
                    <span slot-scope="{ node }">{{ node.label }}</span>
                  </el-tree>
                </el-option>
              </el-select>
            </template>
          </el-table-column>
        </el-table>
      </el-row>
  • :render-header="(h,obj) => addRedStar(h, obj, item.isWrited)"  :动态列表涉及到动态判断是否是必填。借助此函数,在表头添加红色 * 号图标。

  • id、ref、v-model : 都是动态拼接的,在列表中加入多条数据时,确保每个输入框或列表的某一项都是唯一值。

  • scope.row :某一行的数据。

  • scope.column :某一列的数据。

  • scope.row[scope.column.property] : 当前项(单元格)的对应数据。

  • οninput="value=value.replace(/[^\d]/g,'')" : 代码中这段表示只允许输入数字。

  • header-cell-style : 可以为所有表头单元格设置一样的 Style。Element-ui中有介绍。

  • empty-text : 空数据时显示的文本内容。Element-ui中有介绍。

数据来源要依据后端返回数据灵活变通,也可以和后端沟通想要的数据方式。

methods中:

  • 数值类型时有触发检验,只允许输入正整数,必须绑定 id ,且 id 值为唯一值。
  • 只有数值类型只允许输入数字的校验,与οninput="value=value.replace(/[^\d]/g,'')" 配合,也可以单独使用,但多条行数据或一条数据有多个数值校验时,多一个方法校验更有保障,只在HTML中校验有时候会失效,相同,只在方法中使用有时候也会失效。
    // 数值型触发校验
    NumInput(index, len) {
      const num = index.toString() + len
      const idName = 'NumInput' + num
      var input = document.querySelector('#' + idName)
      input.oninput = function() {
        input.value = input.value.replace(/[^\d]/g, '')
      }
    },

有必填项时:

配合上面 :render-header="(h,obj) => addRedStar(h, obj, item.isWrited)"  的代码在methods中相结合:

用 item.isWrited 返回的数值进行判断是否是必填项

    // 是否必填图标
    addRedStar(h, { column }, required) {
      if (required === '0') {
        console.log('column', required)
        return [
          h('span', { style: 'color: red' }, '*'),
          h('span', ' ' + column.label)
        ]
      } else {
        return [
          // h('span', { style: 'color: red' }, '*'),
          h('span', ' ' + column.label)
        ]
      }
    },

校验后的实现效果:

 总结:

这一篇是刚发现问题的时候写了一部分,和之前写的VUE中显示范围有限,元素滚动时el-option超出元素显示范围,是一个模块的问题总结,如果有下拉框飞出问题,可以看看。现在工作没那么忙就赶快看看草稿箱里的文章,尽量都补充完成。

这篇文章中间隔了七个月左右,肯定有思路不连贯的问题,或者有些漏洞没想起来,如果发现请帮忙指出哦~

您可以通过自定义合并规则来实现vue element-ui table单元格的动态合并。以下是一个简单的示例代码: ``` <template> <el-table :data="tableData" ref="multiTable" border> <el-table-column prop="name" label="Name" width="180"> </el-table-column> <el-table-column prop="age" label="Age" width="180"> </el-table-column> <el-table-column prop="gender" label="Gender" width="180" :cell-style="{padding: '0px'}" :render-header="renderHeader" :render-cell="renderCell"> </el-table-column> </el-table> </template> <script> export default { data() { return { tableData: [ { name: 'Tom', age: 18, gender: 'M' }, { name: 'Jane', age: 22, gender: 'F' }, { name: 'John', age: 28, gender: 'M' }, { name: 'Lisa', age: 24, gender: 'F' } ] } }, methods: { // 自定义表头渲染函数 renderHeader(h, { column }) { if (column.property === 'gender') { return h('div', [ h('span', 'Gender'), h('el-checkbox', { on: { change: this.handleMultiHeaderChange } }) ]) } else { return h('div', column.label) } }, // 自定义单元格渲染函数 renderCell(h, { row, column }, index) { const rowspan = this.getMultiRowspan(row, column) if (rowspan === 0) { return '' } else { return h('div', { style: { lineHeight: `${80 * rowspan}px` }, attrs: { rowspan: rowspan } }, row.gender) } }, // 计算单元格跨行数 getMultiRowspan(row, column) { const data = this.tableData let rowspan = 1 let currentIndex = data.indexOf(row) for (let i = currentIndex + 1; i < data.length; i++) { if (data[i][column.property] === row[column.property]) { rowspan++ } else { break } } return rowspan }, // 表头复选框改变事件 handleMultiHeaderChange(value) { const table = this.$refs.multiTable const columns = table.columns columns.forEach((column) => { if (column.property === 'gender') { column.filteredValue = value ? ['M', 'F'] : [] table.store.commit('filterChange', { column: column }) } }) } } } </script> ``` 在这个示例代码,我们使用了自定义渲染函数来渲染表格,其: - `renderHeader` 函数用于渲染表头,其包含一个复选框来控制表格的动态合并; - `renderCell` 函数用于渲染单元格,其通过 `getMultiRowspan` 函数计算出单元格需要跨越的行数。 需要注意的是,这里的示例代码仅供参考,具体实现可能会因为表格数据结构和合并规则的不同而有所不同。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值