el-table 表格封装并改造实现单元格可编辑

本文详细介绍了如何在ElementUI中封装el-table表格,包括设置属性、添加事件和样式,以及实现单元格的可编辑功能,以提升代码复用性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

说明

在使用 element ui 表格组件的时候频繁的引用,相同的业务代码反复,所以萌生了要简易封装一下的想法,做项目的过程中又有了表格单元格可编辑的需求,因此总结记录一下实现过程。

实现

一、el-table表格封装成公共组件

1.创建表格主体(也是即将抽离成公共组件)文件:listEdit.vue (文件名随意)

template部分

<template>

  <el-table
    ref="listEdit"
    :data="tableData"
  >
    <!-- fixed:列是否固定在左侧或者右侧,true 表示固定在左侧;show-overflow-tooltip: 当内容过长被隐藏时显示 tooltip -->
    <el-table-column fixed type="index" width="45" label="序号" show-overflow-tooltip/>
    <!-- 这里用插槽来写表格列,为了方便在调用组件的时候更方便自定义表格列 -->
    <slot name="column">
      <!-- sortable:排序  -->
      <el-table-column v-for="(item,index) of columnList" :key="index" :prop="item.prop" :label="item.label" sortable show-overflow-tooltip/>
    </slot>
  </el-table>

</template>

 script部分

<script>
export default {
  name: "ListEdit",
  props: {
    tableData: {
      type: Array,default:() => []
    },
    columnList: {
      type: Array,default:() => []
    },
  }
}
</script>

基础文件准备完毕 ,接下来对表格功能进一步完善。

2.表格改造

①给表格增加上一些属性设置

height:Table 的高度

highlight-current-row:高亮当前行

border:是否带有纵向边框

header-cell-style:表头单元格样式

cell-style:单元格的 style 的回调方法

row-class-name:行的 className 的回调方法

row-style:行的 style 的回调方法

②给表格增加上一些事件方法

@row-click="rowClick" // 行单击事件

@selection-change="handleSelectionChange" // 选择事件

<template>

  <el-table
    ref="listEdit"
    :data="tableData"
    highlight-current-row
    border
    :height="tableHeight"
    style="width:100%"
    :header-cell-style="{
      color: '#333',
      background: '#f8f8f9',
      padding: '0px',
      fontSize: '12px',
    }"
    :cell-style="{ padding: '0px', height: '22px', cursor: 'pointer' }"
    :row-class-name="rowClassName"
    :row-style="rowStyle"
    @row-click="rowClick"
    @selection-change="handleSelectionChange"
  >
    <!-- fixed:列是否固定在左侧或者右侧,true 表示固定在左侧;show-overflow-tooltip: 当内容过长被隐藏时显示 tooltip -->
    <el-table-column fixed type="index" width="45" label="序号" show-overflow-tooltip/>
    <!-- 这里用插槽来写表格列,为了方便在调用组件的时候更方便自定义表格列 -->
    <slot name="column">
      <!-- sortable:排序  -->
      <el-table-column v-for="(item,index) of columnList" :key="index" :prop="item.prop" :label="item.label" sortable show-overflow-tooltip/>
    </slot>
  </el-table>

</template>
<script>
export default {
  name: "ListEdit",
  props: {
    tableHeight: {
      type: Number,default: () => 300
    },
    tableData: {
      type: Array,default:() => []
    },
    columnList: {
      type: Array,default:() => []
    },
  },
  methods: {
    
    rowClassName({}){ // 行class
      const className = 'resetClass'
      return className
    },

    rowStyle({ row, rowIndex}){ // 行样式
      const styleJson = {}
      // console.log('设置行样式的当前行:',row);
      if (row.isExist === '1') { // 根据当前行的属性来判断,并设置当前行样式
        styleJson.color = '#BCBEC2'
        styleJson.background = '#F4F4F5'
        return styleJson
      } else {
        
        return ''
      }
    },

    rowClick(row) { // 行单击事件
      this.$emit("callBackFun", {
        type: 'rowClick',
        data: row
      })
    },
    
    handleSelectionChange(val) { // 行选 change 事件
      this.$emit("callBackFun", {
        type: 'select',
        data: val
      })
    },

    unSelected() {
      this.$refs.listEdit.setCurrentRow() // setCurrentRow() 设定某行为选中行,不加参数则取消目前高亮行的选中状态
    },
  },
}
</script>
 ③给表格增加样式控制
<style lang="scss" scoped>

  // 鼠标移入高亮
  ::v-deep .el-table__body tr.hover-row>td {
    background-color: #fff2e0 !important;
    // color: #fff;
  }

  // 表格点击高亮
  ::v-deep .el-table__body tr.current-row>td {
    background-color: #FBD9A7 !important;
    // color: #fff;
  }
  // -----------------------------------------------------------------------------------------
  /**
  可以使用CSS的text-overflow属性来实现表格超出部分省略号显示,并且鼠标移入完整显示的效果
  1.首先,在表格的样式中添加以下CSS样式
  2.然后,在表格的列定义中,添加show-overflow-tooltip属性,用于鼠标移入时显示完整内容的提示: 
  */
  ::v-deep .el-table__body-wrapper .cell {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    height: 100%;
  }
  
  ::v-deep .el-table__body-wrapper .cell:hover {
    overflow: visible;
    white-space: normal;
  }
  // -----------------------------------------------------------------------------------------

</style>

至此表格组件封装完毕。

二、组件使用

1.引入

import ListEdit from "@/components/BC-wheelH/zdy-table/elbox/listEdit.vue";

2.声明

  components: {
    ListEdit
  },

3.使用

 template

<ListEdit
  :tableHeight="tableHeight"
  :tableData="tableData"
  @callBackFun="callBackFun"
>
  <!-- 这里使用插槽 v-slot 的值 一定要和组件中 slot 标签 name 属性值相对应 -->
  <template v-slot:column>
    <el-table-column fixed type="selection" width="45" show-overflow-tooltip/> 
  </template>
</ListEdit>

script

<script>
import ListEdit from "@/components/BC-wheelH/zdy-table/elbox/listEdit.vue";
export default {
  components: {
    ListEdit
  },
  data() {
    return {
      tableHeight: 600,
      tableData: [],
    };
  },
  methods: {
    callBackFun(val){
      switch (val.type) {
        case 'rowClick': // 行单击事件
          
        break;
        case 'select': // 行选 change 事件
          
        break;
        default:
        break;
      }
    }
  },
};
</script>

4. 优化

表格的高度height值不方便设置一个固定值所以:

①在组件外包裹一层标签盒子
<div resf="mainBox" style="height:100%">
  <ListEdit
	:tableHeight="tableHeight"
  />
</div>
②组件盒子高度值设100%再获取标签盒子的高度传值进组件,这样盒子标签是什么高度表格就是什么高度
// 获取主体高度(传值给表格撑起高度)
this.tableHeight = this.$refs.mainBox.clientHeight 

三、实现单元格可编辑

1.思路

想实现能编辑输入,首先就想到了表单,所以实现方法就时在表格列写插槽 input 来承载键盘的输入

2.实现

template 部分

<ListEdit
  :tableHeight="tableHeight"
  :tableData="tableData"
>
  <template v-slot:column>
    <el-table-column prop="lengthValue" label="余量长度(mm)" width="120" show-overflow-tooltip>
      <template slot-scope="scope">
        <!-- class 动态绑定 bgf 根据 lengthValueTF 的值来判断 lengthValue 的值合不合理 -->
        <input :class="{'bgf': !scope.row.lengthValueTF}" v-model="scope.row.lengthValue" size="mini" @blur="inputBlur(scope,scope.row.lengthValue)" style="width:100%;height:100%;border:none !important;background:#FBD9A7;outline:none" />
      </template>
    </el-table-column>
  </template>
</ListEdit>

 script 部分

<script>
export default {

  data() {
    return {
      tableData: [
        { lengthValue:100,lengthValueTF:false }
      ],
    };
  },
  methods: {
    inputBlur(val,value){
      // console.log(val);      
    },
  },
};
</script>

 style 部分

.bgf{
  background-color: red !important;
  color: #ffffff;
}

 3.优化

用到表单了就需要校验,所以要与之配套的加入校验方法

①新建 check.js 文件封装校验方法

function checkFun(check,value,callback){ // 校验函数
  // console.log(check,value,callback);
  if (check === 'integer0+') {
    let reg = /^([1-9]\d*|[0]{1,1})$/; // 正整数(包含0)
    // console.log(!reg.test(value));
    if (!reg.test(value)) {
      // console.log('假');
      callback(new Error('请输入正整数'))
    } else {
      // console.log('真');
      callback()
    }
  }
  if (check === 'integer+') {
    let reg = /^([1-9][0-9]*)$/; // 正整数
    // console.log(!reg.test(value));
    if (!reg.test(value)) {
      // console.log('假');
      callback(new Error('请输入正整数'))
    } else {
      // console.log('真');
      callback()
    }
  }
  if (check === 'nonempty') {
    if (value === '' || value == null || value == undefined) {
      callback(new Error('不能为空'));
    } else {
      callback();
    }
  }
}
export default {
  checkFun
};

②引入校验方法,并且在input回调方法里对输入进行校验

<script>
import check from "@/components/BC-wheelH/function/check.js"
export default {

  data() {
    return {
      tableData: [
        { lengthValue:100,lengthValueTF:false }
      ],
    };
  },
  methods: {
    inputBlur(val,value){
      // console.log(val);
      
      check.checkFun('integer0+',value,(err) => {
        if (err) { // 校验报错
          // 单元格加状态来提示当前此数据不合格
          // console.log(err.message);
          this.$message.error('第 ' + (val.$index+1) + ' 行请输入正整数');
          if (val.column.property === "lengthValue") {
            // 改变校验结果标识
            this.tableData[val.$index].lengthValue= false
          }
        } else { 
          if (val.column.property === "margin") {
            // 改变校验结果标识
            this.tableData[val.$index].lengthValue= true
          }
          // console.log('输入有效');

        }
      } )
      
    },
  },
};
</script>

### 实现 Element Plus `el-table` 组件在 Vue3 和 TypeScript 项目中的单元格可编辑功能 为了使 `el-table` 单元格具备可编辑特性,在 Vue3 和 TypeScript 环境下,可以采用如下方法: #### 方法一:通过自定义渲染器实现单击编辑 当检测到特定类型的字段时,设置该字段的渲染方式为输入框或其他交互控件。对于时间类型的数据项,可以创建一个带有事件监听的方法用于切换显示模式与编辑模式。 ```typescript // 定义数据模型接口 interface TableItem { date?: string; name: string; address: string; } const tableData = ref<TableItem[]>([ // 初始化表格数据... ]); function handleEdit(index: number, row: TableItem): void { console.log(`Editing ${index}`, row); } ``` 针对每一列配置不同的渲染逻辑,特别是那些允许用户修改的内容部分: ```html <template> <el-table :data="tableData"> <!-- ...其他列... --> <el-table-column prop="name" label="Name"> <template v-slot="{ row, $index }"> <div @click="handleClick($event, 'edit', $index)"> {{ editingIndex !== $index ? row.name : '' }} <input type="text" v-if="editingIndex === $index" v-model="row.name" @blur="saveEdit('name')" @keyup.enter="saveEdit('name')" /> </div> </template> </el-table-column> <!-- ...更多列... --> </el-table> </template> <script setup lang="ts"> import { ref } from 'vue'; let editingIndex = ref<number | null>(null); async function handleClick(event: MouseEvent, action: string, index: number) { event.stopPropagation(); switch(action){ case 'edit': editingIndex.value = index; break; default: throw new Error(`Unknown action "${action}"`); } } function saveEdit(columnKey:string){ setTimeout(() => { editingIndex.value = null; }, 0); } </script> ``` 此代码片段展示了如何利用模板插槽机制来动态调整视图结构,结合简单的状态管理来控制何时展示原始文本以及何时呈现输入框[^1]。 #### 方法二:集成第三方库或组件增强版表格 如果希望获得更强大的内置支持,则可以选择一些专门设计用来简化此类操作的开源工具包,比如 Vuetify 或 Ant Design Vue 提供的相关解决方案;当然也可以考虑基于现有框架构建自己的高级封装版本。 另外值得注意的是,随着社区的发展和技术的进步,Element Plus 及其周边生态也在不断演进之中,因此建议定期查阅官方文档获取最新的最佳实践指南[^2]。 #### 方法三:使用 `el-input` 结合 `v-model` 进行双向绑定 这是最直接的方式之一,即直接将 `el-input` 放入表格内部通过 `v-model` 来保持同步更新的状态。这种方式简单易懂,适合初学者快速上手尝试。 ```html <!-- 使用 el-input 配合 v-model 实现即时编辑效果 --> <el-table-column property="address" label="Address"> <template #default="scope"> <el-input v-model="scope.row.address"></el-input> </template> </el-table-column> ``` 这种方法虽然直观有效,但在实际应用过程中可能需要额外处理诸如验证规则、保存时机等问题以确保用户体验良好[^3]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值