使用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>
相关推荐
小胖伦的夕阳粉4 分钟前
js 获取树节点上某节点的最底层叶子节点数据
开发语言·javascript·ecmascript
low神5 分钟前
前端在网络安全攻击问题上能做什么?
前端·安全·web安全
@听风吟20 分钟前
力扣之182.查找重复的电子邮箱
大数据·javascript·数据库·sql·leetcode
码力码力我爱你1 小时前
QT + WebAssembly + Vue环境搭建
vue.js·vue·wasm·webassembly·emscripten
qbbmnnnnnn1 小时前
【CSS Tricks】如何做一个粒子效果的logo
前端·css
唐家小妹1 小时前
【flex-grow】计算 flex弹性盒子的子元素的宽度大小
前端·javascript·css·html
涔溪1 小时前
uni-app环境搭建
前端·uni-app
安冬的码畜日常1 小时前
【CSS in Depth 2 精译_032】5.4 Grid 网格布局的显示网格与隐式网格(上)
前端·css·css3·html5·网格布局·grid布局·css网格布局
洛千陨1 小时前
element-plus弹窗内分页表格保留勾选项
前端·javascript·vue.js
小小19921 小时前
elementui 单元格添加样式的两种方法
前端·javascript·elementui