使用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>
相关推荐
David凉宸1 分钟前
Vue 3 项目的性能优化策略:从原理到实践
前端·vue.js·性能优化
小马_xiaoen8 分钟前
Proxy 与 Reflect 从入门到实战:ES6 元编程核心特性详解
前端·javascript·ecmascript·es6
hoiii18719 分钟前
MATLAB SGM(半全局匹配)算法实现
前端·算法·matlab
摘星编程1 小时前
React Native + OpenHarmony:ImageSVG图片渲染
javascript·react native·react.js
计算机学姐1 小时前
基于SpringBoot的民宿预定管理系统【三角色+个性化推荐算法+数据可视化统计】
java·vue.js·spring boot·mysql·信息可视化·intellij-idea·推荐算法
会编程的土豆1 小时前
新手前端小细节
前端·css·html·项目
摘星编程1 小时前
OpenHarmony + RN:Text文本书写模式
javascript·react native·react.js
广州华水科技2 小时前
单北斗GNSS在桥梁形变监测中的应用与技术进展分析
前端
我讲个笑话你可别哭啊2 小时前
鸿蒙ArkTS快速入门
前端·ts·arkts·鸿蒙·方舟开发框架
CherryLee_12102 小时前
基于poplar-annotation前端插件封装文本标注组件及使用
前端·文本标注