模擬元素的title屬性,自定義Vue指令


 1 function showTitle(el, title) {
 2   const popover = getPopover()
 3   const popoverStyle = popover.style
 4 
 5   if (title === undefined) {
 6     popoverStyle.display = 'none'
 7   } else {
 8     const elRect = el.getBoundingClientRect()
 9     const elComputedStyle = window.getComputedStyle(el, null)
10     const rightOffset = parseInt(elComputedStyle.getPropertyValue('padding-right')) || 0
11     const topOffset = parseInt(elComputedStyle.getPropertyValue('padding-top')) || 0
12 
13     popoverStyle.visibility = 'hidden'
14     popoverStyle.display = 'block'
15     popover.querySelector('.popover-content').textContent = title
16     popoverStyle.left = elRect.left - popover.offsetWidth / 2 + (el.offsetWidth - rightOffset) / 2 + 'px'
17     popoverStyle.top = elRect.top - popover.offsetHeight + topOffset + 'px'
18     popoverStyle.display = 'block'
19     popoverStyle.visibility = 'visible'
20   }
21 }
22 
23 function getPopover() {
24   let popover = document.querySelector('.title-popover')
25 
26   if (!popover) {
27     const tpl = `
28       <div class="popover title-popover top fade in" style="position:fixed;">
29         <div class="arrow"></div>
30         <div class="popover-content"></div>
31       </div>
32     `
33     const fragment = document.createRange().createContextualFragment(tpl)
34 
35     document.body.appendChild(fragment)
36     popover = document.querySelector('.title-popover')
37   }
38 
39   return popover
40 }
41 export default {
42   bind(el, binding, vnode) {
43     // 使用 const 聲明一個只讀的常量,其值是需要監聽的事件類型列表
44     const events = ['mouseenter', 'mouseleave', 'click']
45     // 聲明一個處理器,以根據不同的事件類型傳不同的參數
46     const handler = (event) => {
47       if (event.type === 'mouseenter') {
48         // 顯示一個提示框
49         showTitle(el, binding.value)
50       } else {
51         // 隱藏一個提示框
52         showTitle()
53       }
54     }
55 
56     // 在 el 元素上添加事件監聽
57     events.forEach((event) => {
58       el.addEventListener(event, handler, false)
59     })
60 
61     // 在 el 元素上添加一個屬性,以在其他鈎子進行訪問
62     el.destroy = () => {
63       // 移除 el 元素上的事件監聽
64       events.forEach((event) => {
65         el.removeEventListener(event, handler, false)
66       })
67       // 移除 el 元素上的 destroy
68       el.destroy = null
69     }
70   },
71   unbind(el) {
72     // 移除事件監聽和數據綁定
73     el.destroy()
74   }
75 }

使用步驟:

1.建立指令;

2.在要使用的組件中引入並注冊指令

1 import title from '@/directives/title'
2 directives: {
3   title
4 }

3.頁面中使用,將原來的:title=""改為v-title:

1 <a v-for="item in contacts" v-title="item.title" :href="item.link" :style="contactStyle" target="_blank">
2   <i :class="`fa fa-${item.icon}`"></i>
3 </a>

指令的基礎知識補充:

一個指令定義對象可以提供如下幾個鈎子函數(均為可選):

  • bind:只調用一次,指令第一次綁定到元素時調用,在這里可以進行一次性的初始化設置;
  • inserted:被綁定元素插入父節點時調用;
  • update:所在組件的 VNode(虛擬節點)更新時調用,但是可能發生在其子 VNode 更新之前;
  • componentUpdated:指令所在組件的 VNode 及其子 VNode 全部更新后調用;
  • unbind:只調用一次,指令與元素解綁時調用,在這里可以移除綁定的事件和其他數據;
  • 指令鈎子函數會被傳入以下參數:

    • el:指令所綁定的元素,可以用來操作 DOM ;
    • binding:一個對象,binding.value 表示指令的綁定值,如 v-title="'我是標題'" 中,綁定值為'我是標題'
    • vnode:Vue 編譯生成的虛擬節點;
    • oldVnode:上一個虛擬節點,僅在 update 和 componentUpdated 鈎子中可用。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM