el-table+el-popover 踩坑记录

本文介绍如何在Element UI的项目中实现点击table操作按钮弹出带箭头小弹窗的功能,解决过程中遇到的问题包括树形table的配置、Popover触发方式的选择以及多个Popover弹出时的冲突处理。

项目需求,要求点击table后边的操作按钮,弹出修改框。但是又不是大弹框,设计的是带箭头的小弹框,于是想到了el-popover。但是碰到了坑,将解决过程记录下来

  1. 效果图

效果图

  1. 问题

    1. 树形table问题
    2. popover的取消问题
    3. 多个popover弹出(坑)
  2. 解决

    1. 参照el-table的官方apiel-table 树形数据,返回的数据格式中,要携带一个自定义字段,字段内是子table。

      支持树类型的数据的显示。当 row 中包含 children 字段时,被视为树形数据。渲染树形数据时,必须要指定 row-key。支持子节点数据异步加载。设置 Table 的 lazy 属性为 true 与加载函数 load 。通过指定 row 中的 hasChildren 字段来指定哪些行是包含子节点。children 与 hasChildren 都可以通过 tree-props 配置。

      不过要注意自己的element-ui版本,我之前是element-ui@2.3.2版本,里边并不支持树形table,但是看了最新办的api网站,纠结了半天。所以一定要注意自己的element-ui版本,去官网对应是否支持树形table

    2. popover的触发,刚开始是click触发,但是后来发现,只要一点击别的地方,popover就会自动隐藏,并不符合需求,然后查api,发现还有一种触发方式 trigger=“manual”,手动触发

      	<template>
      		<el-popover
      	    placement="bottom"
      	    ref="elPopover"
      	    title="标题"
      	    width="200"
      	    trigger="manual"
      	    content="这是一段内容,这是一段内容,这是一段内容,这是一段内容。"
      	    v-model="visible">
      	    <el-button slot="reference" @click="visible = !visible">手动激活</el-button>
      	  </el-popover>
        </template>
        <script>
        export default {
          data() {
            return {
              visible: false
            };
          }
        };
      </script>
      

      指定一个变量,手动控制这个变量的状态,来达到控制显示隐藏。还有,在非‘manual’中,要控制其显示隐藏,可以通过ref来操作

      this.$refs['elPopover'].doClose()
      

      当时需求还没有修改的时候,要手动关闭弹框。然后在api中并没有发现这个函数,翻看源代码,在其中找到的。记录下。

    3. 多个弹框显示,这是个大坑,足足找了半天,按钮单击一次,结果却出现了两个popover,以为是key重复,检查发现并没有。写了一个单元测试,一个一个增加属性,发现是fiexed:right 导致的,仔细查看页面dom元素,发现了el-table的固定原理
      固定列dom

生成了两个table,固定table会覆盖在基础table上方,所以使用fiexed的话,其实会有两个完全一样的table,我用id来帮顶popover显示隐藏,所以当点击其中一个button时,两个button对应的popover都会显示。真是个大坑。暂时未找到解决方案,只好放弃固定操作列了。

`el-table-column` 是 Element UI 中用于定义表格列的组件,它可以与 `el-popover`(可展开的提示/下拉框)结合使用,提供更多的交互和信息展示功能。`el-popover` 可以在单元格内显示额外的内容,通常在单元格内容上右键点击或者鼠标悬停时弹出。 以下是使用 `el-popover` 在 `el-table-column` 中的基本步骤: 1. 首先,在 `el-table-column` 的 `render` 函数中,创建一个元素作为 `el-popover` 的触发点,例如一个图标或文字。 ```html <template> <el-table-column prop="name" label="Name" :render="renderWithPopover" ></el-table-column> </template> <script> export default { methods: { renderWithPopover(h, { row }) { return h('div', [ // 原始单元格内容 h('span', row.name), // 弹出提示的按钮 h('el-button', { class: 'popover-btn', on: { 'contextmenu.prevent': () => { this.popoverVisible = true; }, mouseenter: () => { this.popoverVisible = true; }, mouseleave: () => { this.popoverVisible = false; } } }, 'More'), // 弹出提示 <el-popover v-model="popoverVisible" placement="bottom-end"> <div slot="reference">More info</div> <p>Here you can display detailed information about the row...</p> </el-popover> ]); } }, data() { return { popoverVisible: false, }; } }; </script> ``` 2. `v-model="popoverVisible"` 将 `popoverVisible` 数据绑定到 `el-popover` 的可见状态,`true` 表示显示,`false` 表示隐藏。 3. `placement="bottom-end"` 定义了提示框的位置,这里设置为底部右侧,你可以根据需求调整。 相关问题: 1. 如何在 `el-popover` 中添加自定义内容? 2. 如何控制 `el-popover` 的显示和隐藏时机? 3. 如何处理 `el-popover` 的关闭事件?
el-table的多列中使用el-popover可以通过在相应的el-table-column标签中设置el-popover的属性来实现。可以参考以下代码示例进行实现: ```html <el-table> <el-table-column label="列1"> <!-- 列1的内容 --> </el-table-column> <el-table-column label="列2"> <!-- 列2的内容 --> <template slot-scope="scope"> <el-popover :ref="`popover-${scope.row.id}`" popper-class="table-list-popper" placement="left" width="200"> <!-- el-popover的内容 --> </el-popover> </template> </el-table-column> <el-table-column label="列3"> <!-- 列3的内容 --> </el-table-column> </el-table> ``` 在以上代码中,el-popover被放置在el-table-column的template标签中,通过slot-scope获取当前行的数据,使用ref属性来标识el-popover的引用。可以根据需要设置el-popover的其他属性,比如placement设置弹出框的位置,width设置弹出框的宽度等。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [解决el-popover嵌入表格多列显示和被表格遮挡的问题](https://blog.csdn.net/Smilelifeeveryday/article/details/123247713)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [解决el-table中使用el-popover组件弹窗显示关闭问题](https://blog.csdn.net/qq_41623635/article/details/131254779)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
在使用 `el-table` 时,若希望在表头中添加输入框并结合 `el-popover` 控制其显示与隐藏,可以通过 `render-header` 自定义表头内容,并在其中嵌套 `el-popover` 组件实现交互逻辑。 ### 通过 `el-popover` 控制筛选框的显示与隐藏 在表头中插入 `el-popover` 可以实现点击图标后弹出输入框的功能,同时避免表头区域过于拥挤。在 `el-table-column` 中通过 `:render-header="renderSpecNameHeader"` 属性绑定一个方法,用于渲染表头内容,并在其中插入 `el-popover`。 ```html <el-table :data="tableData"> <el-table-column prop="volume" label="Volume" width="150" align="right" :render-header="renderSpecNameHeader" sortable show-overflow-tooltip > </el-table-column> </el-table> ``` ```javascript methods: { renderSpecNameHeader(h, { column }) { return h( 'div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center' } }, [ column.label, h('el-popover', { props: { placement: 'top', width: 160, trigger: 'click' }, scopedSlots: { reference: () => h('el-button', { style: { marginLeft: '10px' }, on: { click: (event) => { event.stopPropagation(); } } }, [ h('el-icon', { style: { cursor: 'pointer' } }, [ h('Search') ]) ]) }, default: () => h('el-input', { props: { placeholder: '请输入筛选条件' }, on: { input: (value) => { this.handleFilterChange(value, column.property); } } }) }) ] ); }, handleFilterChange(value, prop) { this.tableData = this.originalData.filter(item => { return item[prop].toString().includes(value); }); } } ``` 上述实现方式中,`el-popover` 的 `trigger` 设置为 `click`,表示点击按钮时弹出输入框;`placement` 设置为 `top`,控制弹出框的位置;`scopedSlots.reference` 用于定义触发弹出框的按钮或图标;`default` 插槽则用于定义弹出内容(即输入框)。 需要注意的是,如果使用 `v-if` 控制 `el-popover` 的显示,或者尝试在多个表头中复用同一个 `el-popover`,可能会导致定位错误或控制台警告。因此,推荐为每个需要筛选功能的表头单独配置一个 `el-popover` 实例,以确保组件的正确渲染和交互逻辑的正常运行[^2]。 此外,虽然可以通过 `:visible="visible"` 控制 `el-popover` 的显隐状态,但在 `render-header` 中直接使用 `v-model` 或 `:visible` 会带来额外的复杂性,尤其是在动态更新状态时。因此,建议优先使用 `trigger="click"` 的方式来控制弹出框的显示与隐藏,以确保组件行为的一致性[^1]。 ### 总结 通过 `render-header` 结合 `el-popover`,可以在 `el-table` 的表头中实现输入框筛选功能,并通过点击图标控制输入框的显示与隐藏。该方法不仅提升了交互体验,也避免了多个表头共享同一个 `el-popover` 所带来的潜在问题。 ---
在使用 `el-table` 输入框筛选结合 `el-popover` 控制显示与隐藏时,如果出现 `el-icon` 未正常显示的问题,通常与组件的渲染方式和事件绑定有关。 ### 使用 `el-popover` 时的渲染问题 当使用 `render-header` 自定义表头内容时,`el-popover` 的 `reference` 插槽需要通过 `scopedSlots` 来定义触发元素。如果直接使用 `el-icon` 作为触发元素,并未正确包裹在 `reference` 插槽中,可能导致图标无法正常显示或事件绑定失败。 在定义 `reference` 插槽时,应确保使用 `el-button` 或其他容器包裹 `el-icon`,以避免渲染异常。例如: ```javascript scopedSlots: { reference: () => h('el-button', { style: { marginLeft: '10px' }, on: { click: (event) => { event.stopPropagation(); } } }, [ h('el-icon', { style: { cursor: 'pointer' } }, [ h('Search') ]) ]) } ``` 上述代码确保 `el-icon` 被正确包裹在 `el-button` 中,并绑定 `click` 事件以阻止事件冒泡,从而避免影响排序等其他功能 [^2]。 ### 图标未显示的可能原因 1. **图标组件未正确引入**:确保 `Search` 图标已通过 `import { Search } from '@element-plus/icons-vue'` 正确引入,并注册到组件中。 2. **`el-icon` 未被正确渲染**:在 `h` 函数中使用 `el-icon` 时,需确保其子元素为图标组件,如 `h('Search')`。 3. **样式未正确应用**:若未设置 `cursor: pointer` 或其他样式,可能导致图标不可见或交互不明显。 ### 控制台警告与组件复用问题 若尝试在多个表头中复用同一个 `el-popover` 实例,并通过 `v-model` 或 `:visible` 控制显隐状态,可能会导致定位错误或控制台警告。因此,推荐为每个需要筛选功能的表头单独配置一个 `el-popover` 实例,以确保组件的正确渲染和交互逻辑的正常运行 [^1]。 --- ### 示例代码 以下为完整 `render-header` 方法示例,确保 `el-icon` 正确显示并绑定事件: ```javascript methods: { renderSpecNameHeader(h, { column }) { return h( 'div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center' } }, [ column.label, h('el-popover', { props: { placement: 'top', width: 160, trigger: 'click' }, scopedSlots: { reference: () => h('el-button', { style: { marginLeft: '10px' }, on: { click: (event) => { event.stopPropagation(); } } }, [ h('el-icon', { style: { cursor: 'pointer' } }, [ h('Search') ]) ]) }, default: () => h('el-input', { props: { placeholder: '请输入筛选条件' }, on: { input: (value) => { this.handleFilterChange(value, column.property); } } }) }) ] ); }, handleFilterChange(value, prop) { this.tableData = this.originalData.filter(item => { return item[prop].toString().includes(value); }); } } ``` --- ### 相关问题 1. 如何在 `el-table` 的表头中使用 `el-select` 实现下拉筛选? 2. 如何在 `el-table` 中实现多列联合筛选功能? 3. 如何在 `el-table` 中实现远程筛选并分页? 4. 在 `el-table` 表头中使用 `el-popover` 时如何避免组件定位错误?
为了在el-table表头中使用el-popover,您需要为每个popover绑定一个独特的变量。以下是一个例子,展示了如何在el-table表头中使用el-popover: ```html <template> <el-table :data="tableData" style="width: 100%"> <el-table-column prop="date" label="日期" width="180"> <template slot="header"> <div> 日期 <el-popover placement="bottom" width="200" trigger="hover" v-model="popoverVisible1" > <p>这是一个日期选择器</p> <el-date-picker v-model="date" type="date" placeholder="选择日期"></el-date-picker> </el-popover> <el-button slot="reference" icon="el-icon-question" size="mini" @click="popoverVisible1 = true" ></el-button> </div> </template> </el-table-column> <el-table-column prop="name" label="姓名" width="180"> <template slot="header"> <div> 姓名 <el-popover placement="bottom" width="200" trigger="hover" v-model="popoverVisible2" > <p>这是一个输入框</p> <el-input v-model="name" placeholder="请输入姓名"></el-input> </el-popover> <el-button slot="reference" icon="el-icon-question" size="mini" @click="popoverVisible2 = true" ></el-button> </div> </template> </el-table-column> </el-table> </template> <script> export default { data() { return { tableData: [ { date: '2022-01-01', name: '张三' }, { date: '2022-01-02', name: '李四' }, { date: '2022-01-03', name: '王五' } ], popoverVisible1: false, popoverVisible2: false, date: '', name: '' }; } }; </script> ``` 在这个例子中,我们为每个el-popover绑定了一个独特的变量(popoverVisible1和popoverVisible2),这样每个popover就可以正常渲染了。同时,我们还为每个popover添加了一个el-button,当用户将鼠标悬停在这个按钮上时,popover就会显示出来。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值