基于ElementUI實(shí)現(xiàn)v-tooltip指令的示例代碼
文本溢出隱藏并使用tooltip
提示的需求,相信在平時(shí)的開發(fā)中會(huì)經(jīng)常遇到。
常規(guī)做法一般是使用 elementui
的 el-tooltip
組件,在每次組件更新的時(shí)候去獲取元素的寬度/高度判斷是否被隱藏。
受益于 element-plus
的虛擬觸發(fā) tooltip
的實(shí)現(xiàn),決定探究在 vue2 上也以一種簡單的方式實(shí)現(xiàn) tooltip
提示。
探究 tooltip 源碼
源碼地址:https://github.com/ElemeFE/element/blob/dev/packages/tooltip/src/main.js
在 render
階段,可以看出 tooltip 組件會(huì)提取插槽中的第一個(gè)子元素進(jìn)行渲染
render(h) { // .... const firstElement = this.getFirstElement(); if (!firstElement) return null; const data = firstElement.data = firstElement.data || {}; data.staticClass = this.addTooltipClass(data.staticClass); return firstElement; },
所以在 mounted
階段, $el
會(huì)獲取到的其實(shí)就是傳入插槽的第一個(gè)元素。
并且在這個(gè)階段,會(huì)給元素添加上mouseenter
、mouseleave
的事件監(jiān)聽,來控制 hover
狀態(tài)下是否顯示 tooltip
mounted() { this.referenceElm = this.$el; if (this.$el.nodeType === 1) { this.$el.setAttribute('aria-describedby', this.tooltipId); this.$el.setAttribute('tabindex', this.tabindex); on(this.referenceElm, 'mouseenter', this.show); on(this.referenceElm, 'mouseleave', this.hide); // ... }
函數(shù)式調(diào)用 tooltip
在了解了 el-tooltip
的運(yùn)行原理之后,我們能夠封裝一個(gè)模板,并且支持函數(shù)式調(diào)用。
通過 getEl 獲取一個(gè) DOM 元素,以便在喚起 tooltip 時(shí)元素的所處位置。
<template> <el-tooltip ref="triggerRef" :manual="true"> <template #content> {{ internalContent }} </template> </el-tooltip> </template> <script> // useOverflowHidden 的邏輯自行定義 import { useOverflowHidden } from './use-overflow-hidden' export default { name: 'TooltipFunction', props: { getEl: { type: Function, default: () => null }, getContent: { type: Function, default: () => '' } }, data() { return { internalContent: '', isHover: false, } }, mounted() { const el = this.getEl() if (!el) return this.$refs.triggerRef.referenceElm = el; el.addEventListener('mousemove', this.onMouseEnter, false) el.addEventListener('mouseleave', this.onMouseLeave, false) }, methods: { onMouseEnter() { if (!this.isHover && useOverflowHidden(this.getEl())) { this.internalContent = this.getContent() this.isHover = true this.$refs.triggerRef.showPopper = true } }, onMouseLeave() { if (this.isHover) { this.isHover = false; this.$refs.triggerRef.showPopper = false } }, onDestroy() { const el = this.getEl() if (!el) return el.removeEventListener('mousemove', this.onMouseEnter) el.removeEventListener('mouseleave', this.onMouseLeave) } }, } </script>
模版完成過后,我們還需要再寫一個(gè)函數(shù)用來調(diào)用 TooltipFunction
。
import Vue from 'vue' import TooltipFunction from './tooltipFunction.vue' function useTooltip(el) { const Ctor = Vue.extend(TooltipWrapper) const instance = new Ctor({ propsData: { getContent, getEl: () => el, }, }) instance.$mount() return instance }
在代碼中,我們只需在 mounted
中對(duì)需要 tooltip
的元素進(jìn)行一次注冊(cè)即可。
<template> <div ref="dataRef">foo</div> </template> <script> import useTooltip from './use-tooltip.js' export default { mounted() { const el = this.$refs.dataRef if (el) { // 獲取 content 的函數(shù)邏輯自行定義 this.tooltipIns = useTooltip(el, () => 'foo') } }, beforeDestory() { this.tooltipIns?.onDestroy() this.tooltipIns?.$destroy() } } </script>
自定義指令 v-tooltip
上述雖然實(shí)現(xiàn)了函數(shù)式調(diào)用 tooltip 的方式,但是還需要對(duì)每個(gè)元素進(jìn)行 ref
聲明獲取 DOM,以及組件銷毀時(shí) tooltip
的生命周期管理。vue 的自定義指令恰好能輕松解決這兩件事情。
function setupTooltipDirection() { const tooltipSymbol = Symbol('tooltip') Vue.directive('tooltip', { bind(el: HTMLElement) { // 這里我們使用 DOM 元素上的 tooltip-content 作為 通信 const instance = createTooltipFactory(el, () => el.getAttribute('tooltip-content') || '') Reflect.set(el, tooltipSymbol, instance) }, unbind(el) { const ins = Reflect.get(el, tooltipSymbol) if (!ins) return ins.onDestroy() ins.$destroy() Reflect.set(el, tooltipSymbol, null) }, }) }
在業(yè)務(wù)中,即可通過簡單的指令實(shí)現(xiàn) tooltip 的提示需求:
<template> <div v-tooltip tooltip-content="hello">hello</div> </template>
到此這篇關(guān)于基于ElementUI實(shí)現(xiàn)v-tooltip指令的示例代碼的文章就介紹到這了,更多相關(guān)ElementUI實(shí)現(xiàn)v-tooltip內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue router 跳轉(zhuǎn)時(shí)打開新頁面的示例方法
這篇文章主要介紹了vue router 跳轉(zhuǎn)時(shí)打開新頁面的示例方法,本文通過示例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-07-07優(yōu)雅的將ElementUI表格變身成樹形表格的方法步驟
這篇文章主要介紹了優(yōu)雅的將ElementUI表格變身成樹形表格的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04vue輕量級(jí)框架無法獲取到vue對(duì)象解決方法
這篇文章主要介紹了vue輕量級(jí)框架無法獲取到vue對(duì)象解決方法相關(guān)知識(shí)點(diǎn),有需要的讀者們跟著學(xué)習(xí)下。2019-05-05Vue預(yù)覽圖片和視頻的幾種實(shí)現(xiàn)方式
本文主要介紹了Vue預(yù)覽圖片和視頻的幾種實(shí)現(xiàn)方式,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07