需求
客户需求多变,原先数据库表不再满足需求,需要被拆解并且表格之间映射关系多对多。
对于前端,需要提供一种修改方式,让用户修正将近1000条数据,并且要让用户感到高效
实现效果总览
点击单元格,就能让单元格变为input,并存储用户修改
实现步骤
分析需求
1、首先排除“点击一行,跳出窗口,修改一行保存”的模式,这对用户来说太慢
2、不可以一次加载/改变较多的dom元素
3、在页面不卡的情况下,尽可能多的展示数据
引入pl-table
pl-table是基于element组件的,其对el-table做了很多优化,其中仅对页面展示区域做渲染,大大提高了性能。
例如:现在一页有30行,原先肯定是一次性渲染好30行数据,向下滚动的时候卡顿的概率高;引入pl-table后,只展示页面能看见的10条数据,性能瞬间提升了一半多。
cnpm i pl-table
import { PlTable, PlTableColumn } from 'pl-table'
点击单元格触发修改事件
1、每一个单元格,都设置一个独有的ref,ref值为列数 + 某行数据的id,即’inputColumn1’+ scope.row.id
2、设置一个全局唯一的参数editdes记录点击的单元格的ref
3、当editdes与当前点击的单元格的ref一致时,将这个单元格变为input框;其余的正常显示
4、当input框处于blur状态下,将editdes清空,刚刚的input框又变为普通数据
<pl-table
ref="multipleTable"
:data="tableData"
border
tooltip-effect="dark"
:header-cell-style="{textAlign: 'center'}"
:highlight-current-row="true"
:use-virtual="true"
:row-height="60"
:height="700"
@selection-change="handleSelectionChange">
<pl-table-column type="selection" width="55" align="center"></pl-table-column>
<pl-table-column label="data1" width="120">
<template slot-scope="scope">
<div class="cell-input-wrap">
<el-input v-if="editdes === 'inputColumn1'+ scope.row.id" v-model.trim="scope.row.data1" :ref="'inputColumn1'+ scope.row.id" @blur="levelDesIt(scope.row)"></el-input>
<div v-else @click="switchDesState('inputColumn1',scope.row.id)" class="default-span">{{scope.row.data1}}</div>
</div>
</template>
</pl-table-column>
</pl-table>
注意点
1、“<el-input v-if="editdes =”此处使用v-if来初始化数据,比v-show更快,因为那么多单元格,修改的地方应该不足30%,且不会修改多次。
2、当有多列参数时,建议一行行书写,而不是循环。因为数据一定会带有自己的规则(最大最小值,时间、正则等)
3、点击单元格触发的switchDesState函数,首先会校验是否为编辑模式,不是则点击无效
代码
vue代码
<template>
<div>
<div style="display: flex;justify-content: space-around;">
<el-switch v-model="isEditMode" active-text="修改模式打开" inactive-text="关闭"></el-switch>
<el-switch v-model="isTestPerformance" active-text="测试性能模式打开" inactive-text="关闭" @change="resetTableData"></el-switch>
</div>
<div>
<pl-table
ref="multipleTable"
:data="tableData"
border
tooltip-effect="dark"
:header-cell-style="{textAlign: 'center'}"
:highlight-current-row="true"
:use-virtual="true"
:row-height="60"
:height="700"
@selection-change="handleSelectionChange">
<pl-table-column type="selection" width="55" align="center"></pl-table-column>
<!-- <pl-table-column label="data1" width="120">
<template slot-scope="scope">
<div class="cell-input-wrap">
<el-input v-if="editdes === 'inputColumn1'+ scope.row.id" v-model.trim="scope.row.data1" :ref="'inputColumn1'+ scope.row.id" @blur="levelDesIt(scope.row)"></el-input>
<div v-else @click="switchDesState('inputColumn1',scope.row.id)" class="default-span">{{scope.row.data1}}</div>
</div>
</template>
</pl-table-column> -->
<!-- 测试性能 -->
<pl-table-column v-for="(item,index) in tableData" :key="item.id" :label="'data' + index" width="120">
<template slot-scope="scope">
<div class="cell-input-wrap">
<el-input v-if="editdes === 'inputColumn'+ index + scope.row.id" v-model.trim="scope.row['data' + index]" :ref="'inputColumn'+ index + scope.row.id" @blur="levelDesIt(scope.row)" ></el-input>
<div v-else @click="switchDesState('inputColumn' + index,scope.row.id)" class="default-span">{{scope.row['data' + index]}}</div>
</div>
</template>
</pl-table-column>
</pl-table>
</div>
<div style="margin-top: 20px">
<el-button @click="toggleSelection()">取消选择</el-button>
</div>
</div>
</template>
<script>
import { _tableData } from './js/tableData.js'
import { PlTable, PlTableColumn } from 'pl-table'
export default {
props: {},
components: {
PlTable,
PlTableColumn
},
data() {
return {
isEditMode: true, // 是否开启编辑模式
tableData: _tableData,
multipleSelection: [],
editdes: null, //标识处于编辑状态的单元格ref
isTestPerformance:true // 是否为测试性能模式
};
},
computed: {},
created() {
this.resetTableData()
},
mounted() {
},
watch: {},
methods: {
// 根据需求,展示简单/复杂的表格
resetTableData() {
this.isTestPerformance ? this.initManyData() : this.tableData = _tableData
},
toggleSelection(rows) {
console.log(rows,'rows')
if (rows) {
rows.forEach(row => {
console.log(row)
this.$refs.multipleTable.toggleRowSelection(row);
});
} else {
this.$refs.multipleTable.clearSelection();
}
},
handleSelectionChange(val) {
this.multipleSelection = val;
},
// 双击span会触发次函数,赋值使得编辑状态开启,row.id为唯一的,不会出现点击一个编辑框,其他也受到影响的情况出现
switchDesState(val,id) {
if(!this.isEditMode) return
this.editdes = val + id;
this.$nextTick(()=>{
this.$refs[this.editdes][0].focus()
// if(this.isTestPerformance){
// this.$refs[this.editdes][0].focus()
// } else {
// this.$refs[this.editdes].focus()
// }
})
},
// 当input框失去焦点时,会触发此函数,使得此编辑状态关闭
levelDesIt(row) {
this.editdes = null;
},
// 初始化一个庞大的表格数据,i为行数,j为列数
initManyData() {
this.tableData = []
let array = []
for(let i = 0;i<=50;i++) {
const obj = { id: i}
for(let j = 0;j<=20;j++) {
obj['data' + j] = `${i}行${j}列`
}
array.push(obj)
}
this.tableData = array
}
}
};
</script>
<style scoped lang="less">
/deep/.el-table .cell {
line-height: 40px;
.cell {
padding: 0;
display: flex;
justify-content: center;
align-items: center;
margin: 0;
height: 40px;
}
.default-span {
display: block;
height: 40px;
width: 100%;
}
.el-input__inner {
margin: 0;
}
}
</style>
js
const _tableData = [
{
id: 1,
date: '2016-05-03',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄',
data0: '11',
data1: '12'
},
{
id: 2,
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄',
data0: '21',
data1: '22'
}
]
export { _tableData }
最后
如果对您有帮助,希望能给个👍评论收藏三连!