如图一个由elementUI el-table组件生成的一个表格,需要在表格头部,完成情况列增加一个图标,点击后浮动一个轻量级的弹层,选择单选项,点击确定,实现批量设置完成情况的功能。一般来说,这种需求,可以通过el-table的头部插槽+el-popover弹出框来实现。结果遇到了一个难题,不论怎么尝试,渲染出来的弹出框中的单选框点击没有任何选中效果,使用vue插件查看数据,v-model对应的值数据确实发生了改变,并且重新打开页面,弹出框的选项才发生变化。期间尝试过使用input框来绑定数据,不论是放在el-popover组件中,还是直接放在el-popover外面,均无法生效。
最后使用render-header的方式解决了问题。
为了方便使用,将表格头部插槽内容单独抽取组件。
表格部分代码:
<el-table-column prop="paramLevelId" :render-header="renderHeader" :label="qualityCheckEvalLevelName" width="100" align="center">
<template slot-scope="{ row, $index }">
<div class="spread">
<div v-show="controlParam.btnName !=='检查' && controlParam.btnName !=='提交'" :style="{color:getColor(row.paramLevelId)}">
{{ getLevelName(row.paramLevelId) }}
</div>
<el-tooltip v-model="row.evalParamLevelIdTips" class="item" :disabled="!row.evalParamLevelIdTips" effect="dark" :content="'请选择'+qualityCheckEvalLevelName" placement="top-end">
<el-select v-show="controlParam.btnName ==='检查' || controlParam.btnName ==='提交'" :ref="`evalParamLevelId${row.number}`" v-model="row.paramLevelId" :placeholder="'请选择'+qualityCheckEvalLevelName" @change="changeTextColor($event,`evalParamLevelId${row.number}`)">
<el-option v-for="item in paramLevelList" :key="item.id" :label="item.levelName" :value="item.id" v-html="'<span style=color:'+item.color+'>'+item.levelName+'</span>'" />
</el-select>
</el-tooltip>
</div>
</template>
</el-table-column>
renderHeader(h, { column, $index }, index) {
return (
<ParamLevelRenderHeader qualityCheckEvalLevelName={this.qualityCheckEvalLevelName} levelCheckModeParamValue={this.levelCheckModeParamValue} controlParam={this.controlParam} paramLevelList={this.paramLevelList}/>
)
}
// 相对定位 需要设置overflow 否则看不到popover弹出框
.checkTableInfo .el-table__header-wrapper{
overflow: visible !important;
}
.checkTableInfo .el-table th{
overflow: visible !important;
}
.checkTableInfo .el-table .cell{
overflow: visible !important;
}
组件代码:
<template>
<div class="d-flex" style="justify-content: center;align-items: center;position: relative">
<span class="flex">{{ qualityCheckEvalLevelName }}</span>
<i v-if="(controlParam.btnName ==='检查' || controlParam.btnName ==='提交') && levelCheckModeParamValue === 'allCheck'" class="el-icon-set-up flex" style="font-size: 18px;cursor: pointer" @click.stop="showBatchParamLevel" />
<el-popover
v-if="(controlParam.btnName ==='检查' || controlParam.btnName ==='提交') && levelCheckModeParamValue === 'allCheck'"
ref="batchParamLevel"
class="batchParamLevel"
placement="bottom"
trigger="click"
>
<div @click.stop>
<div style="text-align: center;" class="font-14">批量设置</div>
<div>
<div>
<el-radio-group v-model="batchSettingParamLevelId" style="padding: 0;margin-top:10px;width: 100%;">
<el-radio v-for="(item,index5) in paramLevelList" :key="index5" style="margin: 5px 0;text-align: center;width: 90%" :label="item.id">{{ item.levelName }}</el-radio>
</el-radio-group>
</div>
</div>
<div class="d-flex j-center">
<el-button class="mt-1" type="primary">确定</el-button>
<el-button class="mt-1" type="primary">重置</el-button>
</div>
</div>
</el-popover>
</div>
</template>
<script>
export default {
name: 'ParamLevelRenderHeader',
props: {
qualityCheckEvalLevelName: { // 分级名称
type: String,
default: ''
},
levelCheckModeParamValue: {
type: String,
default: 'questionCheck'
},
controlParam: { // 控制参数
type: Object,
default: () => ({ btnName: '查看' })
},
paramLevelList: {
type: Array,
default: () => {
return []
}
}
},
data() {
return {
batchSettingParamLevelId: ''
}
},
methods: {
/**
* 显示批量设置质控评价分级
*/
showBatchParamLevel() {
if (this.$refs['batchParamLevel']) {
this.$refs['batchParamLevel'].doShow()
document.addEventListener('click', this.closePopover)
}
},
closePopover() {
if (this.$refs['batchParamLevel']) {
this.$refs['batchParamLevel'].doClose()
document.removeEventListener('click', this.closePopover)
}
}
}
}
</script>
<style>
</style>
代码解析:
1、采用相对定位布局,使得滚动时跟随表格滚动,需要增加额外样式,处理overflow,否则弹出框无法显示。
2、点击图标弹出popover,点击空白处隐藏弹出框,需要在popover中最大的div上加上@click.stop阻止冒泡,否则点击弹出框中的内容也会关闭弹出框。