🏅el-tooltip 组件在全屏状态下不显示提示框问题

📋大纲

🚀简介

1.问题解决

1.1.代码部分

1.2.核心部分

1.3.逻辑部分

2.核心思路

2.1.微/宏任务

3.个人理解


简介

自己遇到了这种问题也是找了许多文章,都进行了尝试,但是基本没什么作用;最后找到了这个一篇文章,看了一下,茅塞顿开;也顺利的解决了这个问题;后来那篇文章找不到了;自己写一篇吧,算是做个记录吧;

如果这篇文章解决了您的问题,帮忙点个赞哦👍;

✍创作不易;


🤖解决问题先~

👀代码部分
vue 复制代码
            <div class="rBtm" ref="tooltipBox">
                <div class="rBtmL">
                    <div class="personBox" v-for="(value, key, index) in dataLeft" :key="key">
                        <div class="personIcon">
                            <img :src="dataLeft[key].icon" alt="">
                        </div>
                        <div class="contentPerson" ref="contentPerson">
                            <el-tooltip :disabled="!isShowTooltip[index]" ref="myTooltip" :append-to-body="false" class="item" effect="dark"
                                :content="computedContent(formData[value.value])" placement="top">
                                <span ref="content" @mouseenter="toggleTooltip(index)" v-if="formData[value.value]" class="ellipsis">{{
                                    formData[value.value] }}</span>
                                <span v-else style="font-size: 14px;color: #ccc;">暂无数据</span>
                            </el-tooltip>
                        </div>
                        <div class="personKey">
                            {{ key }}
                        </div>
                    </div>
                </div>
                <div class="rBtmR">
                    <div class="rBtmR-item" v-for="(value, key) in dataRight" :key="key">
                        <span class="itemKey">{{ key }}</span>
                        <span class="itemValue" v-if="formData[value]">{{ formData[value] }}</span>
                        <span v-else style="font-size: 14px;color: #ccc;">暂无数据</span>
                    </div>
                </div>
            </div>

🎯核心部分

ref

1.tooltipBox 定位 父级盒子

2.myTooltip 定位 组件盒子

3.content 定位 自身

4.toggleTooltip 鼠标事件

5.第 10 行代码 鼠标悬停事件 引用@mouseenter="toggleTooltip(index)"

v-for

注意以上代码用的是 v-for


🎶逻辑部分
javaScript 复制代码
// path:src/utils/common.js

// 检查是否全屏
export function isFull () {
  // 判断浏览器是否处于全屏状态 (需要考虑兼容问题)
  // 火狐浏览器
  let screenFull = document.mozFullScreen ||
    document.fullScreen ||
    // 谷歌浏览器及Webkit内核浏览器
    document.webkitIsFullScreen ||
    document.webkitRequestFullScreen ||
    document.mozRequestFullScreen ||
    document.msFullscreenEnabled
  if (screenFull === undefined) {
    screenFull = false
  }
  return screenFull
}
...
javaScript 复制代码
import { isFull } from '@/utils/common.js';

export const bimGeoMixin = {
    data() {
        return {
            isShowTooltip: [],  // 控制每个 el-tooltip 的显示状态,使用数组来保存多个 tooltip 的状态
        };
    },
    methods: {
        toggleTooltip(index) {
                // 如果全屏状态下,需要特殊处理
                if (!isFull()) return;

                setTimeout(() => {
                    if (this.$refs.myTooltip) {
                        this.$refs.myTooltip.forEach((item) => {
                            // 可以打印 item 看看呢;console.log(item,'item',index)
                            this.$refs.tooltipBox.appendChild(item.popperVM.$el);
                        });
                    }
                }, 100);
        }
};

🤖核心思路

逻辑

🌼 首先要给鼠标悬停的文字部分加上一个鼠标悬停事件;

1.在此事件内判断当前是否为全屏状态 isFull

2.判断浏览器是否处于全屏状态 (需要考虑兼容问题)

3.如果不是全屏状态则不需要特殊处理,直接 return

4.因为某个盒子进入全屏之后,会发生重排重绘,虽然 Vue 的 DOM 更新可能已经完成,但全屏状态触发的布局变化可能还在进行中,因此 this.$nextTick(微任务) 的时机不够晚,无法捕捉到这些变化。所以这里我是用了setTimeout(宏任务)延迟执行了 100 毫秒,给浏览器足够的时间完成全屏引发的布局计算和渲染操作。

全屏模式下的重绘和重排有时比 Vue 的 DOM 更新要慢一些。setTimeout 会等到这些操作结束后再执行代码,从而确保 el-tooltip 的 DOM 正确渲染并可以被附加到新的位置。

5.因为数据是多个,所以代码中用到了 v-for ,所以这里的el-tooltip是多个的,所以需要 变量 isShowTooltip去保存每一个的状态,当然 在toggleTooltip事件中需要传递index,以便分辨出应该触发哪一个el-tooltip组件的提示框;


🤖个人理解

全屏状态下,el-tooltip无法展示提示框的原因可能是因为以下几点:

1.el-tooltip 这些元素都是插入到body里面的,而当某一div全屏后由于层级原因无法显示这些组件;

2.全屏模式下,浏览器会对 DOM 进行重新渲染和布局。在这种情况下,tooltip 可能无法正确计算其位置,导致其未能显示或显示在错误的位置。

上述代码主要是获取 el-toolitp 元素,在元素全屏时,找到el-tooltip的祖父元素然后重新插入到 祖父父级盒子里;


⏰微任务、宏任务

概念:

宏任务(Macrotask)微任务(Microtask) 是指在 JavaScript 异步任务处理中的两种不同类型的任务。这两种任务的执行顺序和优先级不同,理解它们有助于掌握 JavaScript 的事件循环机制

宏任务:

宏任务 是指由宿主环境(如浏览器或 Node.js)调度的任务,每个宏任务会在事件循环的每次循环中执行一个。 常见的宏任务

  • setTimeout

  • setInterval

  • setImmediate(Node.js 环境)

  • I/O 事件回调(如文件读取、网络请求等)

  • UI 渲染(浏览器的重排、重绘)

  • 用户输入事件(如 clickmousedownkeyup 等)

微任务:

微任务 的执行时机比宏任务更早,它们会在当前宏任务执行完毕后、下一个宏任务开始之前执行。微任务通常用于处理异步操作的后续逻辑,比如 Promise 的回调。

常见的微任务:

  • Promise.thenPromise.catchPromise.finally
  • MutationObserver
  • process.nextTick(Node.js 环境)
  • nextTick(()=>{}) (vue)
宏任务与微任务的区别:

执行顺序:

  • 在每轮事件循环中,宏任务会首先执行。
  • 在宏任务执行完后,所有微任务队列中的任务会依次执行,直到微任务队列清空后才开始执行下一轮宏任务。

优先级:

  • 微任务的优先级比宏任务高,因此微任务会在当前的宏任务完成后立即执行,而无需等待下一个事件循环。

任务调度:

  • 宏任务是由事件循环调度的。
  • 微任务是在每个宏任务执行完毕后立即执行的,不会等到下一轮事件循环。
事件循环中的宏任务和微任务流程:
  • 先执行同步代码,所有同步代码都属于当前宏任务
  • 当前宏任务执行完后,执行所有的微任务(如 Promise 回调)。
  • 如果微任务队列清空,检查是否有新的宏任务(如 setTimeout 回调),如果有,执行新的宏任务。
  • 重复上述过程,不断循环。

结束~ 拜拜;

相关推荐
崔庆才丨静觅3 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60614 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了4 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅4 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅4 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅5 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment5 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅5 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊5 小时前
jwt介绍
前端
爱敲代码的小鱼5 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax