使用vue3自定义指令实现Tooltip

效果预览:

实现代码:

directive.js

javascript 复制代码
import { nextTick } from "vue"

function elFover(e) {

	// e.el.classList.add('hover')

	let res = e.el.getBoundingClientRect()
	// console.log(res)

	let dom_tooltip = document.querySelector('.c-tooltip')
	
	if(dom_tooltip) {
		dom_tooltip.style.display = 'block'
		dom_tooltip.querySelector('.ivu-tooltip-inner').innerText = e.val
	
	} else {
		let _div = document.createElement('div')
		_div.innerHTML = `<div class="c-tooltip ivu-tooltip-popper ivu-tooltip-dark ivu-tooltip-transfer" style="z-index: 1099; position: fixed; will-change: top, left; top: 0px; left: 0px;" x-placement="top">
		<div class="ivu-tooltip-content">
			<div class="ivu-tooltip-arrow"></div>
			<div class="ivu-tooltip-inner">${e.val}</div>
		</div>
	</div>`
		document.body.appendChild(_div)

		
	}

	nextTick(() => {
		!dom_tooltip && (dom_tooltip = document.querySelector('.c-tooltip'))
		let _res = dom_tooltip.getBoundingClientRect()

		if(res.top < _res.height) {
			dom_tooltip.style.top = res.bottom +'px'
			dom_tooltip.setAttribute('x-placement', 'bottom')
		} else {
			dom_tooltip.style.top = (res.top - _res.height) +'px'
			dom_tooltip.setAttribute('x-placement', 'top')
		}

		if(res.left < (_res.width - res.width)/2) {
			dom_tooltip.style.left = 0 +'px'
		} else if(window.innerWidth - res.right < (_res.width - res.width)/2) {
			dom_tooltip.style.left = (window.innerWidth - _res.width) +'px'
		} else {
			dom_tooltip.style.left = (res.left + (res.width - _res.width)/2) +'px'
		}

		
	})
	
}

function elLeave() {
	let dom_tooltip = document.querySelector('.c-tooltip')
	
	if(dom_tooltip) {
		dom_tooltip.style.display = 'none'
	}
}

let fb = undefined

export const vFocus = {
	mounted: (el, binding) => {
		fb = elFover.bind(this, {
			el: el,
			val: binding.value
		})
		el.addEventListener('mouseenter', fb)
		el.addEventListener('mouseleave', elLeave)
	},
	// 绑定元素的父组件卸载前调用
  beforeUnmount(el, binding, vnode, prevVnode) {
		el.removeEventListener('mouseenter', fb)
		el.removeEventListener('mouseleave', elLeave)
	},
}

main.ts

TypeScript 复制代码
import { vFocus } from '@/utils/directive.js'
import { createApp } from 'vue'

const app = createApp(App)
app.directive('focus', vFocus)

组件里使用

TypeScript 复制代码
<i class="md-more" v-focus="'更多'"></i>
相关推荐
格子软件15 分钟前
2026年GEO优化系统源码级状态机与多模型调度拆解
java·前端·vue.js·人工智能·vue·geo
HUMHSX1 小时前
Vue 项目启动全流程解析:从入口文件到全局指令注册与页面渲染
前端·javascript·vue.js
有颜有货1 小时前
PMC生产排产的4种算法,一次讲清
java·服务器·前端
小虎牙0071 小时前
Android kotlin图片库Coil源码详解
android·前端
随风一样自由1 小时前
【前端领域】前端开发核心应用场景与落地实践
前端·前端框架
an317422 小时前
弹窗数据流设计的两种高阶架构实践
前端·vue.js·架构
谢尔登2 小时前
【React】 状态管理方案
前端·react.js·前端框架
用户938515635072 小时前
手把手教你实现一个 MCP 文件读取服务器:从协议到代码的深度解析
javascript·人工智能
用户2136610035722 小时前
Vue商品详情与放大镜组件
前端·javascript
半个落月2 小时前
从Tapas小Demo理清localStorage、事件与this
前端·javascript