vue+elment+table动态表头render-header:多列渲染pop后点击显示只显示当前的pop
问题是这样的:在表头渲染一个按钮,点击会弹出当前列的搜索框pop,当点击第二列弹出pop时其余已经弹出的也不会消失。
就算绑定了点击此处以外消失的指令也没用:
那么怎么解决呢,通过实现发现,双击的时候是可以的,也就是@dblclick 但是通过点击改成了双击后出现搜索层肯定不理想,还是想通过单机点出pop然后再点击其它列的搜索旧的pop消失掉
这时候顺着事件触发思路既然能改事件触发那就改成
@mousedown即可
<div slot="reference" style="margin-left:5px;margin-top: 2px;" @mousedown.stop ="popClick" v-click-outside="closeOver">
代码:
父组件表单组件:
<!-- 服务店收货单管理 --> <template> <div class="main"> <el-card class="box-card"> <div class="clearfix"> <span class="card-title">服务店收货单管理</span> </div> <div class="text item"> <el-table :data="tableData" @row-click="clickData" style="width: 100%"> <el-table-column prop="name" label="作业订单" :render-header="renderSpecNameHeader"></el-table-column> <el-table-column prop="name" label="收货单号" :render-header="renderSpecNameHeader"></el-table-column> <el-table-column prop="name" label="订单日期" :render-header="renderSpecNameHeader"></el-table-column> <el-table-column prop="name" label="装箱日期" :render-header="renderSpecNameHeader"></el-table-column> <el-table-column prop="name" label="发货时间" :render-header="renderSpecNameHeader"></el-table-column> <el-table-column prop="name" label="出货历时" :render-header="renderSpecNameHeader"></el-table-column> <el-table-column prop="name" label="妥投时间" :render-header="renderSpecNameHeader"></el-table-column> <el-table-column prop="name" label="物流耗时" :render-header="renderSpecNameHeader"></el-table-column> <el-table-column prop="name" label="物流状态" :render-header="renderSpecNameHeader"></el-table-column> <el-table-column prop="name" label="需求量" :render-header="renderSpecNameHeader"></el-table-column> <el-table-column prop="name" label="未发行数" :render-header="renderSpecNameHeader"></el-table-column> </el-table> </div> <div class="task-page"> <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="pageindex" :page-sizes="[10, 20, 30, 40]" :page-size="pagesize" layout="total, sizes, prev, pager, next, jumper" :total="total" > </el-pagination> </div> </el-card> </div> </template> <script> import TableSelect from './tableSelect.vue' export default { components: { TableSelect }, data() { return { tableData: [{name: '11'}, {name: '22'}], tableDataCopy: [{name: '11'}, {name: '22'}], filters: [], pagesize: 10, pageindex: 1, total: 0, } }, methods: { /** 表头搜索 */ // 渲染**的tableheader renderSpecNameHeader (createElement, { column, $index }) { const self = this // 该列的绑定数据 // console.log(column.label); // 列号 // console.log($index); return createElement( 'div', { style: 'display:inline-flex;' }, [ createElement('div', { domProps: { innerHTML: column.label } }), createElement(TableSelect, { style: 'cursor: pointer;', // 组件 prop props: { type: column.property, options: self.specIdOptions, // 下拉框选项 defaultValue: self.examinerFieldChname, // 默认值 defaultProps: { value: 'examinerFieldName', label: 'examinerFieldChname' } }, // 事件监听器在 `on` 属性内, // 但不再支持如 `v-on:keyup.enter` 这样的修饰器。 // 需要在处理函数中手动检查 keyCode。 on: { selectChange: self.selectChange, resetChange: self.resetChange // click: this.clickHandler }, // 仅用于组件,用于监听原生事件,而不是组件内部使用 // `vm.$emit` 触发的事件。 nativeOn: { // click: this.nativeClickHandler } }) ] ) }, // 搜索回调 selectChange (data) { console.log('搜索回调', data) // 自定义筛选框返回数据进行过滤添加到tableData数组中 const type = data['type'] const value = data['value'] this.filters[type] = value if (value !== '' && type !== '') { this.tableData = this.tableData.filter( item => item[type].toString().toLowerCase().includes(value.toString().toLowerCase()) ) } }, // 重置回调 resetChange (data) { console.log('重置回调', data) delete this.filters[data['type']] var tmpData = this.tableDataCopy for (const key in this.filters) { tmpData = tmpData.filter( item => item[key].toString().toLowerCase().includes(this.filters[key].toString().toLowerCase()) ) } this.tableData = tmpData }, clickData() { this.$router.push({ name:'orderDetail'}) }, // 分页 handleSizeChange() {}, handleCurrentChange() {}, } } </script> <style lang="less" scoped> .main { .clearfix { margin-bottom: 20px; .card-title { font-size: 18px; font-weight: 500; color: #1E1F23; } } .task-page { padding: 0px @pd-16; text-align: right; padding-top: 16px; height: 48px; } } </style>
子组件:pop和出发点组件
<!-- 表头搜索组件 --> <template> <el-popover placement="bottom" width="200" trigger="manual" v-model="visible" @show="showPopover"> <el-input placeholder="请输入内容" v-model="value" clearable @keyup.enter.native="confirm" ref="sInput" > </el-input> <el-button type="primary" size="mini" @click="confirm" style="margin-top:5px;">搜索</el-button> <el-button size="mini" @click="resetData">重置</el-button> <div slot="reference" style="margin-left:5px;margin-top: 2px;" @mousedown.stop ="popClick" v-click-outside="closeOver"> <!-- <div slot="reference" style="margin-left:5px;margin-top: 2px;" @dblclick.stop ="popClick" v-click-outside="closeOver"> --> <img src="../../../assets/songxia/icon-search.png" style="width: 12px;"> </div> </el-popover> </template> <script> export default { data () { return { value: '', visible: false, iconColor: false } }, props: { tableType: { type: String, default: '' }, type: { type: String, default: '' }, defaultValue: { type: String, default: '' }, options: { type: Array, default: function () { return [] } }, defaultProps: { type: Object, default: function () { return { label: 'label', value: 'value' } } } }, watch: { defaultValue (newVal, oldVal) { const self = this self.value = newVal } }, methods: { showPopover () { this.$nextTick(() => { this.$refs.sInput.focus() }) }, resetData () { console.log('reset') this.value = '' this.visible = false this.iconColor = false const self = this self.$emit('resetChange', { type: self.type, value: self.value, tableType: self.tableType }) }, closeOver () { this.visible = false }, popClick (e) { e.stopPropagation() console.log(e) this.visible = !this.visible }, confirm () { this.visible = false this.iconColor = true const self = this if (self.value) { self.$emit('selectChange', { type: self.type, value: self.value, tableType: self.tableType }) } } }, directives: { clickOutside: { bind (el, binding, vnode) { function clickHandler (e) { // 这里判断点击的元素是否是本身,是本身,则返回 if (el.contains(e.target)) { return false } // 判断指令中是否绑定了函数 if (binding.expression) { // 如果绑定了函数 则调用那个函数,此处binding.value就是handleClose方法 binding.value(e) } } // 给当前元素绑定个私有变量,方便在unbind中可以解除事件监听 el.__vueClickOutside__ = clickHandler document.addEventListener('click', clickHandler) }, update () {}, unbind (el, binding) { // 解除事件监听 document.removeEventListener('click', el.__vueClickOutside__) delete el.__vueClickOutside__ } } } } </script>

这样就行了,但是需要注意的是,如果此表单加入了排序 sortable 也是失效的。这时候最好自己指定排序的图标,因为element排序是默认绑定在整个header内的也就是触发header任何dom都会先执行排序干扰显示和隐藏pop的执行。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!