赞
踩
场景:在 el-table 中使用 el-popover ,出现了 loading 加载卡顿的问题,接口返回的数据的时间大概是 140ms ,所以不是接口慢的原因;通过对表中结构的逐步排查,发现是表中的 某一行 所影响的;并且 其中含有 el-popover;因为 el-popover 会渲染出真实的 dom 元素 所以在页面渲染的时候会出现el-table loading 卡顿的情况。
原来的代码是这样的
<ElTable v-loading="loading" :data="tableData" @selection-change="handleSelectionChange" size="small" show-overflow-tooltip @row-dblclick="handleViewDetail" ref="tableRef" :height="tableHeight" highlight-current-row @current-change="handleCurrentRowChange" :row-class-name="tableRowClassName" @sort-change="sort_change" :cell-style="rowClassName" :row-style="{height: '30px'}" :header-cell-style="headerClassName" > //... <el-table-column prop="remark" :label="$t('common.remark')" width="100"> <template #default="scope"> <el-popover :visible="scope.row.visible" placement="top" trigger="click" :width="204"> <el-input v-model="scope.row.remark" style="width: 180px;" :placeholder="$t('common.email.setBlockSize')"/> <div style="text-align: right; margin: 16px 0 0 0;"> <el-button size="small" text @click="() => { scope.row.visible = false; scope.row.remark = ''; }">{{ $t('common.sss16') }} </el-button> <el-button size="small" type="primary" @click="() => { scope.row.visible = false; setRemark(scope.row.mailId, scope.row.remark) }" >{{ $t('common.confirm') }} </el-button > </div> <template #reference> <el-icon @click="scope.row.visible = true" :color="scope.row.remark ? '#40a9ff' : '#dddddd'"> <el-tooltip v-if="scope.row.remark" class="box-item" :content="scope.row.remark" placement="right" > <Memo/> </el-tooltip> <Memo v-else/> </el-icon> </template> </el-popover> </template> </el-table-column> //... </ElTable>
解决办法:因为每次都要渲染真实dom;所以可以将 el-popover 抽离 就像 el-dialog 一样;只不过这里有特别的地方是——每行的数据都是不一样的,还需要动态展示每行的数据。
<el-table-column prop="remark" :label="$t('common.remark')" width="100"> <template #default="scope"> <el-icon :ref="(el) => (refMap[`${scope.row.id}`] = el)" @click="handleRef(refMap[`${scope.row.id}`], scope.row)" :color="scope.row.remark ? '#40a9ff' : '#dddddd'"> <el-tooltip v-if="emailListCheckoutTarget.remark" class="box-item" :content="emailListCheckoutTarget.remark" placement="right" > <Memo/> </el-tooltip> <Memo v-else/> </el-icon> </template> </el-table-column>
抽离的 el-popover
<el-popover virtual-triggering :virtual-ref="tempRef" v-model:visible="visiblePopover" placement="top" :width="204" trigger="click" :popper-options="{ modifiers: [{ name: 'offset', options: { offset: [8, 8] } }] }"> <el-input v-model="emailListCheckoutTarget.remark" style="width: 180px;" :placeholder="$t('common.email.setBlockSize')" @keydown.enter.native.stop="okPopover"/> <div style="text-align: right; margin: 16px 0 0 0;"> <el-button size="small" text @click.stop="cancelPopover">{{ $t('common.sss16') }} </el-button> <el-button size="small" type="primary" @click.stop="okPopover" >{{ $t('common.confirm') }} </el-button > </div> </el-popover>
最重要的一点是,采用这种方式,会出现 重复点击该列的目标对象的时候,会出现 visiblePopover 和 trigger 不同步的问题,表现为 el-popover 闪烁一次;所以需要在用户点击的时候重置 el-popover的显隐状态
//真实dom数组 const refMap = ref([]) //目标dom对象 const tempRef = ref(null) //控制 el-popover 的显隐状态 const visiblePopover = ref(false) //选中的行数据 const emailListCheckoutTarget = ref({}) //触发方法 const handleRef = (ref, item, type) => { tempRef.value = ref //重置 el-popover 显隐状态 visiblePopover.value = false; setTimeout(() => { visiblePopover.value = true; }, 200) emailListCheckoutTarget.value = item; localStorage.setItem('targetItem', JSON.stringify(item.remark)) }
其次还要考虑到什么时候渲染指定的行内容;使用 鼠标 移入、移出 事件;
// 这里是开始点 const mouseEnters = throttle((row) => { //localStorage.getItem("targetItem") 这里是特殊处理,可以根据实际情况处理 if (localStorage.getItem("targetItem") !== row.remark) { visiblePopover.value = false } if (emailListCheckoutTarget.value.remark !== '') { emailListCheckoutTarget.value = row; } }, 300) const mouseLeaves = throttle((row) => { if (localStorage.getItem("targetItem") === row.remark) { // 防止popover 消失 visiblePopover.value = false; } }, 300)
这是两个方法:提交数据;取消提交
const cancelPopover = () => {
visiblePopover.value = false;
emailListCheckoutTarget.value.remark = ''
}
const okPopover = () => {
//这是提交到后端
setRemark(emailListCheckoutTarget.value.id, emailListCheckoutTarget.value.remark)
emailListCheckoutTarget.value = {};
visiblePopover.value = false;
}
经过上面的一顿操作后,肉眼可见的速度提高了,大约优化了 0.5s 左右。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。