vue对el-table的二次封装,双击单元格编辑,避免表格输入框过多卡顿
为什么要做这个
项目中表格能编辑的单元格越来越多,界面慢慢的变得卡顿,起初准备自定义每个单元格默认为文字,双击聚焦输入,输入失焦切换回文字,但是这样没有通用性,每次都得copy一份,比较麻烦,于是就想做个封装
怎么做?
先上完整代码
封装文件name:MyTable
<template>
<el-table v-bind="$attrs" v-on="$listeners" :data="tableData" @cell-dblclick="cellDblclick">
<template v-for="(item, index) in myColumns">
<!-- 如果是序号、选择器、或只需要展示的数据就直接展示 -->
<el-table-column
:key="item.prop + '#' + index"
:type="item.type"
width="55px"
v-if="['index', 'selection'].includes(item.type)"
>
</el-table-column>
<el-table-column
:key="item.prop + '#' + index"
:label="item.label"
:prop="item.prop"
v-else-if="item.justShow"
>
</el-table-column>
<!-- 否则先展示为文字,双击渲染为下拉、输入、文本域等输入框 -->
<el-table-column v-bind="item" :key="item.prop + '##' + index" v-else>
<template slot-scope="scope">
<template v-if="formViewMethod(scope, index)">
<component
:is="
typeof item.render === 'function'
? handleRendel(item.render, scope)
: item.render
"
:scope="scope"
></component>
</template>
<span v-else v-html="scope.row[item.prop]"></span>
</template>
</el-table-column>
</template>
</el-table>
</template>
<script>
export default {
name: "MyTable",
props: {
myColumns: {
require: true,
},
tableData: {
type: Array,
default: () => []
},
},
data() {
return {
editColumnId: null,
editRowIndex: -1,
};
},
methods: {
formViewMethod(scope) {
return (
scope.$index === this.editRowIndex &&
this.editColumnId === scope.column.id
);
},
handleRendel(renderFunc, scope) {
let cel = this.$createElement;
return {
render: () => {
return renderFunc(cel, scope);
},
};
},
/**
* 双击单元格开启编辑模式
*@param {paraName}
*/
cellDblclick(row, column, cell) {
// console.log(row, column, cell, event);
this.editColumnId = column.id;
this.editRowIndex = this.tableData.findIndex((item) => item === row);
// 切换为输入状态时自动聚焦
this.$nextTick(() => {
// 日期和输入框可以聚焦,但是下拉选择不会展开
cell.querySelector(".el-input__inner")?.focus();
// 下拉选择可用下面的,建议用row.prop或自定义一个名称自行判断下
// cell.querySelector(".el-input__inner")?.click();
});
},
},
};
</script>
复制代码
使用:
<template>
<div>
<my-table :myColumns="columns" :tableData="tableData"></my-table>
</div>
</template>
<script>
import MyTable from "./MyTable.vue";
export default {
name: "UseMyTable",
components: {
MyTable,
},
data() {
return {
columns: [
{
label: "序号",
type: "index",
},
{
label: "全选",
type: "selection",
},
{
label: "姓名",
prop: "name",
justShow: true,
},
{
label: "日期",
prop: "date",
render: (h, { row }) => {
return (
<el-date-picker
v-model={row.date}
type="date"
placeholder="选择日期"
></el-date-picker>
);
},
},
{
label: "地址",
prop: "address",
render: (h, { row }) => {
return <el-input v-model={row.address}></el-input>;
},
},
{
label: "选择",
prop: "selectDate",
render: (h, { row }) => {
return (
<el-select v-model={row.selectDate}>
<el-option label="111" value="111"></el-option>
<el-option label="222" value="222"></el-option>
</el-select>
);
},
},
],
tableData: [
{
date: "2016-05-02",
name: "王小虎",
address: "上海市普陀区金沙江路 1518 弄",
selectDate: "",
},
{
date: "2016-05-04",
name: "王小虎",
address: "上海市普陀区金沙江路 1517 弄",
selectDate: "",
},
],
};
},
};
</script>
复制代码
关键位置说明
- 双击切换的实现
首先利用el-table的cell-dblclick的事件,通过它的回调参数row, column计算出点击的哪一个单元格editColumnId和editRowIndex,然后通过这两个值将编辑的单元格渲染出来,其他的一律为非编辑状态。
渲染出来后,利用cell-dblclick的第三个参数cell实现自动聚焦输入,提升用户体验
cellDblclick(row, column, cell) {
// console.log(row, column, cell, event);
this.editColumnId = column.id;
this.editRowIndex = this.tableData.findIndex((item) => item === row);
// 切换为输入状态时自动聚焦
this.$nextTick(() => {
// 日期和输入框可以聚焦,但是下拉选择不会展开
cell.querySelector(".el-input__inner")?.focus();
// 下拉选择可用下面的,建议用row.prop或自定义一个名称自行判断下
// cell.querySelector(".el-input__inner")?.click();
});
},
复制代码
- render渲染,注意套一层将参数传入
<component
:is="
typeof item.render === 'function'
? handleRendel(item.render, scope)
: item.render
"
:scope="scope"
></component>
复制代码
效果图
存在的问题
-
el-select不能通过上面的focus自动展开,需要用click事件,可以在row里面的单独定义一个标识特殊处理
-
不双击别的单元格的话,前一个单元格不会变成文本状态。
初步考虑在document上加点击回调,点击表格外面就将编辑位置置为空(editColumnId和editRowIndex)
- 输入框和文本高度不一样,切换状态时表格高度会变化,不好看,得调整样式
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END