基于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月前
|
开发者 容器
44.[HarmonyOS NEXT RelativeContainer案例一] 掌握组件锚点布局:打造灵活精准的UI定位系统
在HarmonyOS NEXT的UI开发中,精确控制组件位置是构建复杂界面的关键。RelativeContainer作为一种强大的布局容器,通过锚点系统提供了精确定位能力,使开发者能够创建出灵活且精准的UI布局。本教程将详细讲解如何使用RelativeContainer的锚点布局功能,帮助你掌握这一核心技术。
202 4
|
5月前
|
设计模式 缓存 容器
06.HarmonyOS Next UI进阶:Text组件与视觉样式完全指南
在HarmonyOS Next应用开发中,Text组件是最基础也是最常用的UI元素之一。它不仅用于显示文本内容,还可以通过丰富的样式属性实现各种视觉效果。掌握Text组件的样式设置,是构建精美UI界面的基础技能。
297 1
|
2月前
|
Linux Go iOS开发
IDA 9.2 发布:Golang 改进、新 UI 组件、类型解析等
IDA Pro 9.2 (macOS, Linux, Windows) - 强大的反汇编程序、反编译器和多功能调试器
634 0
|
4月前
|
Web App开发 前端开发 JavaScript
Element UI框架中自定义input组件的placeholder样式。
确保这些样式在你的应用程序CSS文件中定义,且该文件已正确加载到项目中。通过以上方法,可以控制Element UI组件中input的placeholder样式,使其满足特定的设计要求。这些更改都是基于CSS伪元素进行的,因此并不会对DOM结构产生改变,保持了原有结构的简洁和高效。
447 12
|
4月前
|
存储 JavaScript 前端开发
element ui <el-date-picker> 设置展示当前月
在 Element UI 中,使用 `el-date-picker` 的 `value-format` 属性可将日期值格式化为指定字符串。设置 `type=&quot;month&quot;` 时,绑定值默认为 Date 对象,通过 `value-format=&quot;yyyy-MM&quot;` 可将其转为如 &quot;2023-05&quot; 格式,便于存储与处理。
1034 0
|
9月前
|
前端开发 安全 开发工具
【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
587 90
【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
5月前
|
移动开发 开发者
仓颉开发语言入门教程:常见UI组件介绍和一些问题踩坑
仓颉开发语言即将发布一周年,虽已有知名App应用,但教程稀缺且官网文档不够完善。幽蓝君推出系列教程,从零开始系统讲解移动开发。本期介绍常用UI组件:按钮、文本、图片、输入框与搜索框的使用方法及注意事项,帮助开发者快速上手仓颉语言。
|
9月前
|
JavaScript 数据安全/隐私保护
Vue Amazing UI 组件库(Vue3+TypeScript+Vite 等最新技术栈开发)
Vue Amazing UI 是一个基于 Vue 3、TypeScript、Vite 等最新技术栈开发构建的现代化组件库,包含丰富的 UI 组件和常用工具函数,并且持续不断维护更新中。另外,组件库全量使用 TypeScript,支持自动按需引入和 Tree Shaking 等,能够显著提升开发效率,降低开发成本。
566 5
Vue Amazing UI 组件库(Vue3+TypeScript+Vite 等最新技术栈开发)
|
9月前
|
人工智能 自然语言处理 前端开发
Flame:开源AI设计图转代码模型!生成React组件,精准还原UI+动态交互效果
Flame 是一款开源的多模态 AI 模型,能够将 UI 设计图转换为高质量的现代前端代码,支持 React 等主流框架,具备动态交互、组件化开发等功能,显著提升前端开发效率。
1345 1
|
8月前
|
安全 API 开发者
深入探索ArkUI中的@LocalBuilder装饰器:构建高效可维护的UI组件
在ArkUI框架中,组件化开发至关重要。@LocalBuilder作为自API version 12引入的装饰器,专注于组件内部私有构建,确保封装性与安全性。本文解析其工作原理、参数传递机制及与@Builder的区别,结合典型场景代码示例,助开发者掌握这一工具。通过状态驱动UI更新、复杂组件组合等实践,优化性能并提升代码可维护性,推动高效UI架构构建。
243 0

热门文章

最新文章