vue3.0 组件篇 Tooltip

本文详细介绍了Vue3 dxUI库中的Tooltip组件,它用于提供简短的提示信息,增强用户体验。组件支持多种触发方式、定位选项、自定义内容和宽度,并考虑了可访问性。文章还分享了开发思路、组件安装使用方法、参数说明及事件监听。同时,提供了完整的组件代码示例,帮助开发者理解和应用Tooltip组件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

组件介绍

“Tooltip” 组件是一种用户界面元素,通常用于提供简短的信息、描述、提示或帮助文本,以解释某个元素的功能或提供额外的上下文信息。通常, “Tooltip” 以弹出框或气泡的形式出现,用户可以将鼠标悬停在目标元素上以触发显示。以下是关于 “Tooltip” 组件的介绍和特点:

  1. 简短文本:

    • “Tooltip” 组件通常包含简短的文本消息,用于解释或提供有关目标元素的信息。
  2. 鼠标悬停触发:

    • “Tooltip” 通常在用户将鼠标悬停在目标元素上时触发显示,以提供额外的上下文信息。
  3. 定位和位置:

    • “Tooltip” 组件通常可以根据目标元素的位置自动定位,以确保它不会超出屏幕边界或遮挡目标元素。
  4. 自动关闭:

    • 通常, “Tooltip” 会自动关闭,当用户将鼠标移出目标元素或等待一段时间后。
  5. 手动关闭:

    • 一些 “Tooltip” 组件支持用户手动关闭,通常通过点击关闭按钮或其他指示方式。
  6. 可访问性:

    • 良好的 “Tooltip” 组件应该考虑到可访问性,以确保它对于使用辅助技术的用户也是可访问的。
  7. 自定义内容:

    • 开发人员通常可以自定义 “Tooltip” 组件的内容、样式和触发方式,以满足特定需求。
  8. 响应式设计:

    • “Tooltip” 组件通常支持响应式设计,以适应不同屏幕尺寸和设备类型。
  9. 多用途:

    • “Tooltip” 可以用于不同类型的元素,包括按钮、链接、图标、表单字段等,以提供帮助和上下文信息。

“Tooltip” 组件对于增强用户体验、提供额外的上下文信息或解释界面元素非常有用。它通常用于网页应用程序、移动应用程序、桌面应用程序等,以提供用户友好的界面。前端框架和库通常提供了 “Tooltip” 组件的实现,或者你可以自行编写代码来创建适合你应用程序需求的提示功能。

开发思路

Tooltip是一种小型弹出框,它显示有关特定页面元素的信息,例如按钮、链接或图标。Tooltip通常以半透明的气泡形式呈现,并出现在页面元素的旁边或下方。

它可以改善用户体验,使用户更容易理解页面元素的功能和意图。用户可以通过将鼠标悬停在页面元素上来快速了解有关该元素的信息,而无需离开当前页面或浏览其他页面。

  1. 定位问题,很重要,top topLeft topRight bottom bottomLeft bottomRight left right,tooltip可以出现在不同的位置
  2. 采用默认插槽的方式,将需要tooltip的内容放置
  3. 通过父组件传入的visible进行手动控制tooltip的显现和隐藏
  4. 可以自定义tooltip背景色,如果自定义了,文字为白色
  5. 监听状态的变化,通过$emit 实现@change的调用
  6. 自定义tooltip的宽度,这个很重要
  7. 默认触发tooltip的方式为hover ,触发的方式还有click,如果从父组件传入了visible,hover和click将会失效

组件安装与使用

需要先安装vue3-dxui

yarn add vue3-dxui

或者

npm install vue3-dxui

全局main.ts中引入css

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import 'vue3-dxui/dxui/dxui.css'

createApp(App).use(store).use(router).mount('#app')

按需引入

<script>
import { Tooltip } from 'vue3-dxui'

export default {
  components: {
  	Tooltip
  }
}
</script>

组件代码

<template>
  <div
    @mouseenter="handleHoverTooltipShow"
    @mouseleave="handleHoverTooltipHide"
    @click="handleClickTooltipChange"
    class="dx-tooltip-warpper"
    :class="`trigger-${trigger} position-${position}`"
  >
    <!-- 在顶层通过传入的visible进行控制 -->
    <div v-show="visible !== undefined ? visible : true" class="dx-tooltip-max-width">
      <!-- 在内层通过组件自身的tooltipvisible进行控制 -->
      <div
        v-show="tooltipVisible"
        class="dx-tooltip-content-warpper"
        :style="
          background ? { background, color: '#fff', borderColor: background, width } : { width }
        "
      >
        <div class="tooltip-title">
          {{ title }}
        </div>
        <div
          class="tooltip-icon"
          :style="background ? { background, color: '#fff', borderColor: background } : {}"
        />
      </div>
    </div>
    <slot />
  </div>
</template>

<script lang="ts">
import { ComponentInternalInstance, getCurrentInstance, ref, PropType, watch } from 'vue'

import { Data } from './types'

export default {
  props: {
    // tooltip的内容
    title: {
      required: false,
      default: '',
      type: String
    },
    // tooltip的触发方式 hover click
    trigger: {
      required: false,
      default: 'hover',
      type: String
    },
    // 可以用来手动控制tooltip的出现或者消失
    visible: {
      required: false,
      default: undefined,
      type: Boolean as PropType<boolean | undefined>
    },
    // tooltip出现的位置
    position: {
      required: false,
      default: 'topLeft',
      type: String
    },
    // 可以设置tooltip的背景颜色
    background: {
      required: false,
      default: '',
      type: String
    },
    // 自定义tooltip的宽度,tooltip的宽度受被包裹元素的影响,这里提供自定义
    width: {
      required: false,
      default: '',
      type: String
    }
  },
  watch: {
    // 对外界传入的visible进行监听,选用了vue2的写法,因为外界传入的visible可能不是一个ref只是一个简单的boolean值
    visible(newval: boolean) {
      // this.$emit 会报错 说$emit在类型里面不存在,所以用这样的方式,但实际上是存在的,将来可能需要改进下,知道的朋友说一下
      const that: any = this
      that?.$emit('change', newval)
    }
  },
  setup(propsData: Data) {
    let tooltipVisible = ref(false)
    if (propsData.visible !== undefined) {
      tooltipVisible = ref(true)
    }

    const currentInstance: ComponentInternalInstance | null = getCurrentInstance()

    const handleHoverTooltipShow = () => {
      if (propsData.trigger === 'hover' && propsData.visible === undefined) {
        tooltipVisible.value = true
      }
    }

    const handleHoverTooltipHide = () => {
      if (propsData.trigger === 'hover' && propsData.visible === undefined) {
        tooltipVisible.value = false
      }
    }

    const handleClickTooltipChange = () => {
      if (propsData.trigger === 'click' && propsData.visible === undefined) {
        tooltipVisible.value = !tooltipVisible.value
      }
    }

    // 如果是组件内部自己维护的tooltipVisible,就用vue3的watch触发监听,实现change的回调
    watch(tooltipVisible, (newval) => {
      currentInstance?.emit('change', newval)
    })

    return {
      tooltipVisible,
      handleHoverTooltipShow,
      handleHoverTooltipHide,
      handleClickTooltipChange
    }
  }
}
</script>

<style lang="scss" scoped>
@import '@/scss/layout.scss';

.dx-tooltip-warpper {
  display: inline-block;
  position: relative;
  cursor: pointer;

  .dx-tooltip-max-width {
    text-align: initial;
    position: absolute;
    z-index: 1000;
    width: 100%;
  }

  .dx-tooltip-content-warpper {
    display: inline-block;
    text-align: initial;
    padding: 6px 10px;
    background: $background-color;
    border: $border;
    border-radius: 4px;
    min-width: 80px;
  }

  .tooltip-title {
    font-size: 14px;
    z-index: 1000;
  }

  .tooltip-icon {
    width: 12px;
    height: 12px;
    position: absolute;
    z-index: 999;
    transform: rotate(45deg);
    background: $background-color;
    border-bottom: $border;
    border-right: $border;
  }
}

.dx-tooltip-warpper.position-topLeft {
  .dx-tooltip-content-warpper {
    position: absolute;
    bottom: calc(100% + 10px);
  }
}

.dx-tooltip-warpper.position-top {
  .dx-tooltip-max-width {
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
  }
  .dx-tooltip-content-warpper {
    position: absolute;
    bottom: calc(100% + 10px);
    left: 50%;
    transform: translateX(-50%);
  }

  .tooltip-icon {
    position: absolute;
    left: 50%;
    margin-left: -4px;
  }
}

.dx-tooltip-warpper.position-topRight {
  .dx-tooltip-max-width {
    position: absolute;
    right: 0;
  }

  .dx-tooltip-content-warpper {
    position: absolute;
    right: 0;
    bottom: calc(100% + 10px);
  }

  .tooltip-icon {
    position: absolute;
    right: 12px;
  }
}

.dx-tooltip-warpper.position-bottomLeft {
  .dx-tooltip-max-width {
    position: absolute;
    bottom: -10px;
  }

  .dx-tooltip-content-warpper {
    position: absolute;
  }

  .tooltip-icon {
    position: absolute;
    top: -6px;
    transform: rotate(-135deg);
  }
}

.dx-tooltip-warpper.position-bottom {
  .dx-tooltip-max-width {
    position: absolute;
    bottom: -10px;
    left: 50%;
    transform: translateX(-50%);
  }
  .dx-tooltip-content-warpper {
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
  }

  .tooltip-icon {
    position: absolute;
    top: -6px;
    left: 50%;
    margin-left: -4px;
    transform: rotate(-135deg);
  }
}

.dx-tooltip-warpper.position-bottomRight {
  .dx-tooltip-max-width {
    position: absolute;
    bottom: -10px;
    right: 0;
  }

  .dx-tooltip-content-warpper {
    position: absolute;
    right: 0;
  }

  .tooltip-icon {
    position: absolute;
    top: -6px;
    right: 12px;
    transform: rotate(-135deg);
  }
}

.dx-tooltip-warpper.position-left {
  .dx-tooltip-max-width {
    position: absolute;
    top: 50%;
  }

  .dx-tooltip-content-warpper {
    position: absolute;
    transform: translateX(-100%) translateY(-50%);
    left: -10px;
  }

  .tooltip-icon {
    position: absolute;
    right: -6px;
    top: calc(50% - 6px);
    transform: rotate(-45deg);
  }
}

.dx-tooltip-warpper.position-right {
  .dx-tooltip-max-width {
    position: absolute;
    top: 50%;
    margin-left: calc(100% + 10px);
  }

  .dx-tooltip-content-warpper {
    position: absolute;
    transform: translateY(-50%);
  }

  .tooltip-icon {
    position: absolute;
    left: -6px;
    top: calc(50% - 6px);
    transform: rotate(135deg);
  }
}
</style>

参数说明

名称说明
titlestring类型,tooltip的内容
triggerhover 或者 click , tooltip的触发方式,默认值是hover
visibleboolean类型,可以通过父组件来自定义控制trigger的消失或隐藏
positiontooltip出现的位置,默认值是 topLeft
background背景色,如果有背景色设置,字体默认是白色
widthtooltip的宽度

事件

事件名称说明
@change当tooltip显示或者隐藏状态发生改变时触发,返回值是当前tooltip的visible的值

关于dxui组件库

dxui组件库是我个人搭建的vue3 前端交互组件库,倾向于pc网站的交互模式。

  1. 如果你有任何问题,请在博客下方评论留言,我尽可能24小时内回复。
  2. dxui新上线的官网域名变更 http://dxui.cn
  3. npm 官方链接 https://www.npmjs.com/package/vue3-dxui
  4. 如果你想看完整源码 https://github.com/757363985/dxui

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

可缺不可滥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值