基于Vue2.0仿Element UI的el-tooltip实现一个气泡框组件,支持多数据类型的显示和内容为空时不显示气泡框

简介: 该文章介绍了如何基于Vue2.0仿照Element UI的el-tooltip组件实现一个自定义的气泡框组件,该组件能够根据内容是否为空智能显示或隐藏,支持多种数据类型的显示。

场景:因为有个需求就是鼠标经过可多选的 el-select 选择器时,需要有个气泡框显示已选的内容,其实 el-tooltip 气泡框可以满足需求,就是用 el-tooltip 气泡框来包裹 el-select 选择器,但是当选择器一个也没选中,即内容为空时不应该也显示气泡框,有点影响美观。应该就是若内容为空时,气泡框可以直接不显示出来。

因此,通过网上查找相关案例,自行设计一个仿Element UI的气泡框el-tooltip组件,不过多多少少不及官方Element UI的气泡框 el-tooltip 组件,只是可以满足内容为空时不显示气泡框,也就不需要v-if来判断内容是否为空,频繁创建与销毁组件,以及避免带来的用户体验问题。同时,支持输入的内容为整型、字符串、数组等,会有各自的显示。

父组件:index.vue

<template>
  <div>
    <div style="width: 300px; height: 300px; margin: 300px 200px; padding: 20px; background-color: #eee;">

      <!-- 气泡框内容为空 -->
      <MagicPopover :content="''">
        <el-button size="mini">气泡框内容为空,直接不显示气泡框</el-button>
      </MagicPopover>

      <br /><br /><br />


      <!-- 气泡框内容为整型 -->
      <MagicPopover :content="content1">
        <el-button size="mini">气泡框内容为整型</el-button>
      </MagicPopover>

      <br /><br /><br />

      <!-- 气泡框内容为字符串 -->
      <MagicPopover :content="content2">
        <el-button size="mini">气泡框内容为字符串</el-button>
      </MagicPopover>

      <br /><br /><br />

      <!-- 气泡框内容为数组 -->
      <MagicPopover :content="content3">
        <el-button size="mini">气泡框内容为数组</el-button>
      </MagicPopover>
    </div>    
  </div>
</template>

<script>
import MagicPopover from "./components/magicPopover";

export default {
   
   
  components: {
   
   
    MagicPopover
  },
  data: () => ({
   
   
    content1: 5201314,
    content2: 'HelloWorld',
    content3: [5201314, 'HelloWorld']
  })
}
</script>

<style scoped>

</style>

子组件:magicPopover.vue

<template>
  <div
    class="esse-popover"
    @mouseenter="handleMouseEnterEvent"
    @mouseleave="handleMouseLeaveEvent"
  >
    <transition name="fade">
      <div
        class="esse-popover-wrapper"
        ref="essePopoverWrapperRef"
        v-if="isView && content != null && content != ''"
      >
        <!-- 判断是否为数组 -->
        <div v-if="(content instanceof Array)">
          <p v-for="(item, key) of content" :key="key">{
   
   {
   
    item }}</p>
        </div>

        <!-- 其他类型,包括字符串、整型、对象... -->
        <div v-else>
          <p>{
   
   {
   
    content }}</p>
        </div>
      </div>
    </transition>

    <div ref="essePopoverSlotRef">
      <slot></slot>
    </div>
  </div>
</template>

<script>
export default {
   
   
props: [
  'content'
],
data() {
   
   
  return {
   
   
    isView: false,
  }
},
methods: {
   
   
  /**
   * 鼠标进入事件
   */
  handleMouseEnterEvent(event) {
   
   
    this.isView = true;
    this.$nextTick(() => {
   
   
      this.draw();
    })
  },

  /**
   * 鼠标离开事件
   */
  handleMouseLeaveEvent(event) {
   
   
    this.isView = false;
  },

  /**
   * 渲染气泡框
   */
  draw() {
   
   
    if (this.content != null && this.content != '') {
   
   
      document.body.appendChild(this.$refs.essePopoverWrapperRef);
      let {
   
   left, top, width} = this.$refs.essePopoverSlotRef.getBoundingClientRect();
      // console.log('this.$refs.essePopoverSlotRef.getBoundingClientRect() =>', this.$refs.essePopoverSlotRef.getBoundingClientRect());
      const offsetTop = 10;// 偏移高度
      const offsetleft = width / 2;// 便宜位移,从左边计算
      this.$refs.essePopoverWrapperRef.style.top = top - offsetTop + 'px';
      this.$refs.essePopoverWrapperRef.style.left = left + offsetleft + 'px';
      document.styleSheets[0].addRule('.esse-popover-wrapper::before','display: block; left: 50%; bottom: 0');// 显示三角形伪类元素
    }
  },
},
}
</script>

<style scoped>
  .esse-popover {
   
   
    width: auto;
    display: inline-block;
    position: relative;
  }

  .esse-popover-wrapper {
   
   
    position: absolute;
    z-index: 99;
    width: 250px;
    height: auto;
    padding: 6px;
    border: 1px solid #ebeef5;
    box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.2);
    background-color: #fff;
    transform: translate(-50%, -100%);
  }

  .esse-popover-wrapper p {
   
   
    margin: auto;
    font-size: 13px;
  }

  /* 使用伪元素创建小三角形 */
  .esse-popover-wrapper::before {
   
   
    content: "";
    position: absolute;
    border-width: 6px 6px 0 6px;
    border-style: solid;
    border-color: transparent;
    border-top-color: #fff;
    transform: translate(-50%, 100%);
  }
  /* / 使用伪元素创建小三角形 */

  /* 淡入淡出效果 */
  .fade-enter-active {
   
   
    /* transition: opacity 1s; */
    transition: all ease 1s;
  }
  .fade-leave-active {
   
   
    /* transition: opacity 0.3s; */
    transition: all ease 0.3s;
  }
  .fade-enter, .fade-leave-to /* .fade-leave-active, 2.1.8 版本以下 */ {
   
   
    opacity: 0;
  }
  /* / 淡入淡出效果 */
</style>

效果如下~

参考资料

Vue基础popover弹出框编写及bug问题分析 - 编程宝库

目录
相关文章
|
5天前
|
API UED 容器
深入探索 Element UI:自定义滚动条与弹出层管理的技巧
在这篇博客中,我们将深入探讨 Element UI 中的自定义滚动条及弹出层管理技巧。文章详细介绍了 el-scrollbar 组件的使用和参数设置,以及 PopupManager 如何有效管理弹出层的 z-index。我们还将探讨如何实现灵活的全屏组件,利用 vue-popper 创建自定义弹出层,最后介绍 ClickOutside 指令的用法。这些高级技巧将帮助你提升 Element UI 应用程序的用户体验与交互灵活性。
36 1
深入探索 Element UI:自定义滚动条与弹出层管理的技巧
|
4天前
|
JavaScript 索引
Vue开发中Element UI/Plus使用指南:常见问题(如Missing required prop: “value“)及中文全局组件配置解决方案
Vue开发中Element UI/Plus使用指南:常见问题(如Missing required prop: “value“)及中文全局组件配置解决方案
32 0
|
15天前
Element-UI组件的使用
【10月更文挑战第1天】
28 0
|
1月前
|
JavaScript
从零开始写一套广告组件【一】搭建基础框架并配置UI组件库
其实这个从零有点歧义,因为本质上是要基于`tdesign-vue-next`来进行二次封装为一套广告UI组件库,现在让我们在一起快乐的搭建自己的广告UI库之前,先对以下内容做出共识:
61 0
从零开始写一套广告组件【一】搭建基础框架并配置UI组件库
|
2月前
|
JavaScript
基于Element UI或Element Plus实现具有倒计时的Message消息提示
本文介绍了如何在Element UI或Element Plus框架中实现具有倒计时功能的消息提示组件,支持多次点击生成多个独立倒计时的消息提示,并提供了详细的实现代码和使用示例。
269 1
基于Element UI或Element Plus实现具有倒计时的Message消息提示
|
2月前
|
存储 搜索推荐 Java
探索安卓开发中的自定义视图:打造个性化UI组件Java中的异常处理:从基础到高级
【8月更文挑战第29天】在安卓应用的海洋中,一个独特的用户界面(UI)能让应用脱颖而出。自定义视图是实现这一目标的强大工具。本文将通过一个简单的自定义计数器视图示例,展示如何从零开始创建一个具有独特风格和功能的安卓UI组件,并讨论在此过程中涉及的设计原则、性能优化和兼容性问题。准备好让你的应用与众不同了吗?让我们开始吧!
|
2月前
|
JavaScript 前端开发 安全
[译] 在 Vue 组件中分离 UI 和业务逻辑。
[译] 在 Vue 组件中分离 UI 和业务逻辑。
|
2月前
|
开发者 C# Android开发
明白吗?Xamarin与Native的终极对决:究竟哪种开发方式更适合您的项目需求,让我们一探究竟!
【8月更文挑战第31天】随着移动应用开发的普及,开发者面临多种技术选择。本文对比了跨平台解决方案Xamarin与原生开发方式的优势与劣势。Xamarin使用C#进行跨平台开发,代码复用率高,可大幅降低开发成本;但因基于抽象层,可能影响性能。原生开发则充分利用平台特性,提供最佳用户体验,但需维护多套代码库,增加工作量。开发者应根据项目需求、团队技能和预算综合考量,选择最适合的开发方式。
90 0
|
2月前
|
JavaScript 前端开发 开发者
决战前端之巅!Element UI与Vuetify谁才是Vue.js组件界的霸主?一场关于颜值与实力的较量!
【8月更文挑战第30天】本文对比了两款热门的Vue.js组件库——Element UI与Vuetify。Element UI由饿了么团队打造,提供多种高质量UI组件,设计简洁大方。Vuetify基于Material Design规范,支持Vue.js 2.0及3.0版本,具备前瞻性。两者均涵盖表单、导航、数据展示等组件,Element UI配置选项丰富,而Vuetify则提供了更深层的样式定制功能。开发者可根据项目需求及个人偏好选择合适的组件库。
165 0
|
2月前
|
JavaScript 开发者 UED
Vue.js组件库大对决:Element UI与Vuetify,开发者的罗密欧与朱丽叶!
【8月更文挑战第30天】Element UI和Vuetify是Vue.js开发中的热门组件库,前者简洁高效,后者遵循Material Design,国际化程度高。两者均提供丰富的组件支持,但Vuetify组件更多样,设计更灵活;Element UI在性能和中文支持上更优。文档方面,Element UI更直观易懂,而Vuetify配置灵活但学习成本稍高。选择时需综合考虑项目需求、团队背景及设计风格,以达到最佳开发效果。
128 0