溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

vue如何自定義加載指令

發(fā)布時(shí)間:2022-06-08 09:19:18 來(lái)源:億速云 閱讀:306 作者:iii 欄目:開(kāi)發(fā)技術(shù)

本文小編為大家詳細(xì)介紹“vue如何自定義加載指令”,內(nèi)容詳細(xì),步驟清晰,細(xì)節(jié)處理妥當(dāng),希望這篇“vue如何自定義加載指令”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來(lái)學(xué)習(xí)新知識(shí)吧。

前言

用過(guò)element-ui的都應(yīng)該知道,里面有一個(gè)loading組件,有兩種調(diào)用方法:指令和服務(wù)。但是只有一種加載效果,為了豐富加載效果和方便使用,于是寫(xiě)了一個(gè)自定義loading指令。

創(chuàng)建加載組件

首先,需要?jiǎng)?chuàng)建loading組件,展示需要的加載效果,因人而異,不再贅述。

創(chuàng)建指令

指令文件

首先,創(chuàng)建一個(gè)js文件用于書(shū)寫(xiě)自定義指令,在這個(gè)文件中導(dǎo)入Vueloading組件:

import Vue from 'vue'
import loading from './loading.vue'

創(chuàng)建構(gòu)造器

主要是使用Vue.extend構(gòu)造器,可以簡(jiǎn)單的理解為傳入一個(gè)組件作為參數(shù),然后返回該組件的類(lèi),可以使用這個(gè)類(lèi)new出實(shí)例。

// loading組件作為參數(shù)傳入
const loadingConstructor = Vue.extend(loading)

書(shū)寫(xiě)指令

在此之前,設(shè)定好指令的參數(shù),在本人的項(xiàng)目中,參數(shù)有兩種方式:1.傳入一個(gè)布爾值,代表是否開(kāi)啟加載;2.傳入一個(gè)對(duì)象,對(duì)象中包含是否開(kāi)啟遮罩、提示文字、加載背景顏色等屬性,方便開(kāi)發(fā)時(shí),高度自定義laoding。
指令的觸發(fā)主要是在update中,該屬性可接收一個(gè)函數(shù),每次指令的參數(shù)改變時(shí)都會(huì)觸發(fā)該函數(shù),就是在這里判斷開(kāi)啟或者關(guān)閉加載效果。 整體代碼如下,附有詳細(xì)注釋?zhuān)?/p>

const loadingDirective = Vue => {
  Vue.directive('custLoading', {
    /**
     * binding:
     * 1.可傳單個(gè)參數(shù),為布爾值;
     * 2.也可用json傳多個(gè)參數(shù){ loading, tip, background }
     *  2.1 loading { boolean } 是否開(kāi)啟遮罩
     *  2.2 tip { string } 提示文字
     *  2.3 background { string } 加載背景顏色
     * */
    // update: 參數(shù)變化時(shí)觸發(fā)
    update: function (el, binding, vnode) {
      const value = binding.value
      let backup = {}
      // 判斷參數(shù)類(lèi)型,將參數(shù)都轉(zhuǎn)換為對(duì)象,方便后續(xù)統(tǒng)一處理
      typeof value === 'boolean' ? (backup.loading = value) : (backup = value || {})
      // 取出所有的參數(shù)
      const { loading, tip, background } = backup
      // 根據(jù)loading參數(shù)判斷開(kāi)啟或者關(guān)閉加載效果,開(kāi)啟和關(guān)閉函數(shù)后續(xù)會(huì)講到
      loading ? createLoading(el, tip, background) : close(el?.customLoadingInstance?.$el)
    },
    // unbid: 指令卸載時(shí)觸發(fā)
    unbind: function (el, binding) {
      const { loading } = binding.value || {}
      // 如果還在展示加載特效,則關(guān)閉
      loading && close(el?.customLoadingInstance?.$el)
    }
  })
}
export default loadingDirective

開(kāi)啟函數(shù)

在上面的指令中,當(dāng)開(kāi)啟的參數(shù)為true時(shí),回會(huì)調(diào)用一個(gè)createLoading函數(shù)用于將加載效果加入到指令掛載的元素上,具體思路如下:
1.在調(diào)用時(shí),我們傳入了三個(gè)參數(shù)給它,分別是掛載有自定義加載指令的元素、加載時(shí)的提示、加載背景顏色,詳細(xì)可見(jiàn)上面的指令代碼。
2.在執(zhí)行之前,還需要進(jìn)行判斷當(dāng)前的Vue實(shí)例是否運(yùn)行在服務(wù)器上,如果是,此時(shí)不需要將加載效果展示出來(lái);或者該元素之前是否已經(jīng)帶有加載特效,如果是的話,沒(méi)必要在開(kāi)啟一次,不然到時(shí)會(huì)出現(xiàn)多層加載效果,既多余,又讓頁(yè)面顯得混亂。
3.判斷需要使用加載效果的元素是否還存在,不存在,則掛載到#main或者document.body上。
4.判斷元素上是否存在定位或者其他條件,在本人的項(xiàng)目中,使用絕對(duì)定位來(lái)使加載效果鋪滿元素,因此需要進(jìn)行判斷,如果沒(méi)有定位,則加上relative。
5.使用loadingConstructor,創(chuàng)建loading實(shí)例,將實(shí)例作為子元素通過(guò)appendChild,放進(jìn)需要展示的元素中,就可以展示出來(lái);同時(shí),在展示的元素上增加一個(gè)屬性customLoadingInstance,用于記錄當(dāng)前的loading實(shí)例,方便后續(xù)的銷(xiāo)毀。
整體代碼如下:

const createLoading = (target, tip= '加載中,請(qǐng)稍候...', background) => {
  // 判斷是否允許開(kāi)啟加載特效
  if (Vue.prototype.$isServer || target?.customLoadingInstance) return
  const mainEL = document.querySelector('#main')
  // 判斷展示加載效果的元素是否存在
  const parentNode = target || mainEL || document.body
  // 判斷父級(jí)是否存在定位,沒(méi)有則添加定位
  const position = getComputedStyle(parentNode)?.position
  (!position || position === 'static') && (parentNode.style.position = 'relative')
  // 創(chuàng)建loading實(shí)例
  const instance = new loadingConstructor({
    el: document.createElement('div'),
    data: { background, tip, parentNodeWidth: parentNode.clientWidth, isShow: true }
  })
  // 注意:loading實(shí)例是一個(gè)Vue組件對(duì)象,真正的DOM放在實(shí)例的$el屬性上
  parentNode.appendChild(instance.$el)
  parentNode.customLoadingInstance = instance
  
  return instance
}

關(guān)閉函數(shù)

有開(kāi)啟就得有結(jié)束,當(dāng)開(kāi)啟的參數(shù)為false時(shí),關(guān)閉加載效果。該函數(shù)接收loading實(shí)例的$el,其實(shí)就是加載效果的DOM元素,思路如下:
1.為了使加載組件看起來(lái)是逐漸消失的,不得在第一時(shí)間將加載效果的DOM元素刪除,而是給它添加一個(gè)逐漸消失的動(dòng)畫(huà),通過(guò)一個(gè)class設(shè)定。
2.設(shè)定動(dòng)畫(huà)消失時(shí)間,由loading組件內(nèi)部實(shí)現(xiàn)在規(guī)定時(shí)間內(nèi),將整個(gè)加載效果執(zhí)行完成或者淡出頁(yè)面。也可省略此步驟,直接就將其移除。 之所以加入這個(gè)效果,是為了用戶視覺(jué)上感受更好。
3.創(chuàng)建定時(shí)器,用于在加載效果消失時(shí),刪除加載效果的DOM元素。同2,也可直接移除。

const close = (target) => {
  if (!target) return
  // 添加逐漸消失的class
  target.className += ' custom-loading-disappear'
  // 獲取loading實(shí)例
  const instance = target?.parentNode?.customLoadingInstance
  //  設(shè)定消失時(shí)間。
  instance?.$data?.dur && (instance.$data.dur = 0.8)
  // 設(shè)定定時(shí)器,用于在加載效果消失時(shí),刪除加載效果的`DOM`元素。
  let timer = setTimeout(() => {
    if (target && target.parentNode) {
      // 將customLoadingInstance 屬性置為null,才不會(huì)干擾下一次開(kāi)啟
      target.parentNode.customLoadingInstance = null
      // 將加載效果的DOM元素移除
      target.parentNode.removeChild(target)
    }
    clearTimeout(timer)
    timer = null
  }, 1100)
}

讀到這里,這篇“vue如何自定義加載指令”文章已經(jīng)介紹完畢,想要掌握這篇文章的知識(shí)點(diǎn)還需要大家自己動(dòng)手實(shí)踐使用過(guò)才能領(lǐng)會(huì),如果想了解更多相關(guān)內(nèi)容的文章,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

vue
AI