多 el-popover 的使用,怎么保证不卡顿?

3,370 阅读3分钟

本文正在参加「金石计划」

场景

Popover 弹出框 其实在我们的项目中,有很多使用场景。比如:

  • 在小图旁边预览大图
  • 点击某个内容,展示详情或者扩展内容
  • 点击删除等按钮进行二次确认
  • hover 某个内容,展示其隐藏内容等

弹出框的位置可以出现在其周边各个位置。

image.png

image.png

image.png

image.png

多 el-popover 怎么处理?

需求:就是需要在列表的每一项里边都展示出 el-popover;或者是在 表格里边 嵌套 el-popover;同一个页面或者同一个模块里边多处需要使用到 el-popover ......

如果我们每一处都使用一份 el-popover,数据量大的时候,或者使用多的话,就会造成卡顿,你不妨试试?!

解决办法:多处共用一份 el-popover。那怎么具体做呢?

el-popover 提供了一个虚拟触发的功能,可以将触发内容和下拉内容分开,那这样就可以只用一个 popover 组件去涵盖所有需要用到的场景。

vue2

不废话了,上代码:

// popover 弹出框组件
<el-popover
  v-if="showPop_hide"
  ref="popover_hide"
  :reference="reference_hide"
  :append-to-body="false"
  placement="right"
  width="450"
  trigger="click">
  <pop-gdp
    :analysis-loading="analysisLoading"
    :analysis-data="analysisData"
    @popPieClick="popPieClick"
    @popLineClick="popLineClick"/>
</el-popover>


// 触发 弹框的内容
<div
  v-for="(item, index) in showUnselected"
  :key="item.index"
  :ref="'pop_hide'+index"
  :class="analysisActive === 'hide' + index ? 'active' : ''"
  @click="analysisClick('hide', item, index)"
>
  <div class="show-word_item">
    ......
  </div>
</div>

上处 pop-gdp 组件内容可据判断来具体展示哪一部分内容。

// data 数据
data() {
    return {
      showPop_hide: false,
      reference_hide: {},
      termIndex_hide: -1,
    }
}
// 核心触发 方法
analysisClick(type, item, index) {
  ......
  
  this.analysisPop(type, item, index)
  
  ......
},
analysisPop(type, item, index) {
  if (this['termIndex_' + type] === index && this['showPop_' + type]) {
    this.$refs['popover_' + type] && this.$refs['popover_' + type].doClose()
  }
  this['showPop_' + type] = false
  this['reference_' + type ] = this.$refs['pop_' + type + index][0]
  this.$nextTick(() => {
    // 等待显示的 popover 销毁后再 重新渲染新的 popover
    this['showPop_' + type] = true
    this['termIndex_' + type] = index
    this['termItem_analysis'] = item
    this.$nextTick(() => {
      // 此时才能获取 refs 引用
      this.$refs['popover_' + type].doShow()
    })
  })
},

以上代码基本就把这个核心都展示全了,大家如果有类似需求,也可以使用该方式。列表、表格、只要是多 el-popover 都可以使用该方式。

效果如图:

image.png

自定义指令 v-popover

vue2 还提供了一个自定义指令,我们也可以使用。使用方式如下:

<el-popover
    ref="popover-hover"
    placement="top-start"
    title="标题"
    trigger="hover"
    content="这是hover 激活。"
>
</el-popover>
<el-button v-popover:popover-hover>hover 激活</el-button>


<el-popover
    ref="popover-click"
    placement="bottom"
    title="标题"
    trigger="click"
    content="这是click 激活。"
>
</el-popover>
<el-button v-popover:popover-click>click 激活</el-button>


<el-popover
    ref="popover-focus"
    placement="right"
    title="标题"
    trigger="focus"
    content="focus 激活"
>
</el-popover>
<el-button v-popover:popover-focus>focus 激活</el-button>


<el-popover
    ref="popover"
    placement="bottom"
    title="标题"
    trigger="manual"
    content="这是一段内容,这是一段内容,这是一段内容,这是一段内容。"
    v-model="visible"
>
</el-popover>
<el-button v-popover:popover @click="visible = !visible">
    手动激活
</el-button>

vue3

vue3 版本的 el-popover,就注意到这个场景了,给暴露出来该使用方法了,虚拟触发:

像 Tooltip 一样,Popover 可以由虚拟元素触发,这个功能就很适合使用在触发元素和展示内容元素是分开的场景。通常我们使用 #reference 来放置我们的触发元素, 用 triggering-element API,您可以任意设置您的触发元素 但注意到触发元素应该是接受 mouse 和 keyboard 事件的元素。

<template>
  <el-button ref="buttonRef" v-click-outside="onClickOutside">
      Click me
  </el-button>

  <el-popover
    ref="popoverRef"
    :virtual-ref="buttonRef"
    trigger="click"
    title="With title"
    virtual-triggering
  >
    <span> Some content </span>
  </el-popover>
</template>

<script setup lang="ts">
import { ref, unref } from 'vue'
import { ClickOutside as vClickOutside } from 'element-plus'
const buttonRef = ref()
const popoverRef = ref()
const onClickOutside = () => {
  unref(popoverRef).popperRef?.delayHide?.()
}
</script>

v-popover 将被废弃

Vue3版本 Tips: v-popover 将被废弃,请使用 virtual-ref 作为替代。

您可以使用指令性方式弹出窗口,但这种方法不再推荐 ,因为这使得应用程序变得复杂, 您可以参考虚拟触发来实现一样的效果。

<template>
  <el-button
      v-popover="popoverRef"
      v-click-outside="onClickOutside"
  >Click me</el-button>

  <el-popover
    ref="popoverRef"
    trigger="click"
    title="With title"
    virtual-triggering
    persistent
  >
    <span> Some content </span>
  </el-popover>
</template>

<script setup lang="ts">
import { ref, unref } from 'vue'
import { ClickOutside as vClickOutside } from 'element-plus'
const buttonRef = ref()
const popoverRef = ref()
const onClickOutside = () => {
  unref(popoverRef).popperRef?.delayHide?.()
}
</script>

小结

本文重点介绍的是 多 el-popover 的使用方式,确实我们的业务场景会遇到,以至于 element-plus 版本都直接把该方法当作官方文档提供出来了。希望能帮助到大家!

最近比较迷恋自定义指令,所以在本文也是提了一嘴自定义指令 v-popover 的使用方式,后续有时间的话,再给大家分享一下最近的自定义指令合集。