1. 程式人生 > 程式設計 >Vue中使用裝飾器的方法詳解

Vue中使用裝飾器的方法詳解

目錄
  • 前言
  • 什麼是裝飾器?
  • 裝飾器的使用
  • 中使用裝飾器
  • 不使用裝飾器
  • 中使用裝飾器
  • 一些常用的裝飾器
    • 1. 函式節流與防抖
    • 2. loading
    • 3. 確認框
  • 總結

    前言

    相信各位在開發中一定遇到過二次彈框確認相關的需求。不管你使用的是UI框架的二次彈框元件,還是自己封裝的彈框元件。都避免不了在多次使用時出現大量重複程式碼的問題。這些程式碼的積累導致專案的可讀性差。專案的程式碼質量也變得很差。那麼我們如何解決二次彈框程式碼重複的問題呢?使用裝飾器

    什麼是裝飾器?

    Decorator是ES7的一個新語法。Decorator通過對類、物件、方法、屬性進行修飾。對其新增一些其他的行為。通俗來說:就是對一段程式碼進行二次包裝。

    裝飾器的使用

    使用方法很簡單 我們定義一個函式

    const  decorator =  (target,name,descriptor) => {
     var oldValue = descriptor.value;
     descriptor.value = function(){
        alert('哈哈')
        return oldValue.apply(this,agruments)
           }
      return descriptor
    }
    // 然後直接@decorator到函式、類或者物件上即可。

    裝飾器的目的旨在對程式碼進行復用。下面我們先來一個小例子看看

    js中使用裝飾器

    //定義一個裝飾器 
    const log = (target,descriptor) => {
      var oldValue = descriptor.value;
      descriptor.value = function() {
        console.log(`Calling ${name} with`,arguments);
        return oldValue.apply(this,arguments);
      };
      return descriptor;
    }
       //計算類
      class Calculate {  
     
      //使用裝飾器
      @log() 
      function  subtraction(a,b){
         return  a - b
       }
     }
     
     const operate  = new Calculate()
      operate.subtraction(5,2)

    不使用裝飾器

    const log = (func) => {
      if(typeof(func) !== 'function') {
        throw new Error(`the param must be a function`);
      }
      return (...arguments) => {
        console.info(`${func.name} invoke with ${arguments.join(',')}`);
        func(...arguments);
      }
    }
    
    const subtraction = (a,b) => a + b;
    
    const subtractionLog = log(subtraction);
    
    subtractionLog(10,3); 

    這樣一對比你會發現使用裝飾器後代碼的可讀性變強了。裝飾器並不關心你內部程式碼的實現。

    vue 中使用裝飾器

    如果你的專案是用vue-cli搭建的 並且vue-cli的版本大於2.5 那麼你無需進行任何配置即可使用。如果你的專案還包含eslit 那麼你需要在eslit中開啟支援裝飾器相關的語法檢測

    //在 eslintignore中新增或者修改如下程式碼:
    parserOptions: {
        ecmaFeatures:{
          // 支援裝飾器
          legacyDecorators: true
        }
      }

    加上這段程式碼之後eslit就支援裝飾器語法了。

    通常在專案中我們經常會使用二次彈框進行刪除操作:

    //decorator.js
    //假設專案中已經安裝了 element-ui
    import { MessageBox,Message } from 'element-ui'
    /**
     * 確認框
     * @param {String} title - 標題
     * @param {String} content - 內容
     * @param {String} confirmButtonText - 確認按鈕名稱
     * @param {Function} callback - 確認按鈕名稱
     * @returns
       **/
    export function confirm(title,content,confirmButtonText = '確定') {
      return function(target,descriptor) {
        const originValue = descriptor.value
        descriptor.value = function(...args) {
     http://www.cppcns.com     MessageBhttp://www.cppcns.comox.confirm(content,title,{
            dangerouslyUseHTMLString: true,distinguishCancelAndClose: true,confirmButtonText: confirmButtonText
          }).then(originValue.bind(this,...args)).catch(error => {
            if (error === 'close' || error === 'cancel') {
              Message.info('使用者取消操作'))
            } else {
              Message.info(error)
            }
          })
        }
        return descriptor
      }
    }

    如上程式碼 confirm方法裡執行了一個element-ui中的MessageBox元件 當用戶取消時 Message元件會提示使用者取消了操作。

    我們在test()方法上用裝飾器修飾一下

    import { confirm } from '@/util/decorator'
    import axios form 'axios'
    export default {
    name:'test',data(){
    return {
      delList: '/merchant/storeList/commitStore'
        }
      }
    },methods:{
     @confirm('刪除門店','請確認是否刪除門店?')
      test(id){
       const {res,data} = axios.post(this.delList,{id})
       if(res.rspCd + '' === '00000') this.$message.info('操作成功!')
      }
    }

    此時使用者點選某個門店進行刪除。裝飾器將會起作用。彈出如下圖所示:

    Vue中使用裝飾器的方法詳解

    當我點選取消時:

    Vue中使用裝飾器的方法詳解

    tips: 使用者取消了操作.被修飾的test方法不會執行

    當我們點選確定時:

    Vue中使用裝飾器的方法詳解

    介面被呼叫了 並且彈出了message

    一些常用的裝飾器

    下面小編羅列了幾個小編在專案中常用的幾個裝飾器,方便大家使用

    1. 函式節流與防抖

    函式節流與防抖應用場景是比較廣的,一般使用時候會通過throttle或debounce方法對要呼叫的函式進行包裝,現在就可以使用上文說的內容將這兩個函式封裝成裝飾器, 防抖節流使用的是lodash提供的方法,大家也可以自行實現節流防抖函式哦

    import { throttle,debounce } from 'lodash'
    /**
     * 函式節流裝飾器
     * @param {number} wait 節流的毫秒
     * @param {Object} options 節流選項物件
     * [options.leading=true] (boolean): 指定呼叫在節流開始前。
     * [options.trailing=true] (boolean): 指定呼叫在節流結束後。
     */
    export const throttle =  function(wait,options = {}) {
      return function(target,descriptor) {
        descriptor.value = throttle(descriptor.value,wait,options)
      }
    }
    
    /**
     * 函式防抖裝飾器
     * @param {number} wait 需要延遲的毫秒數。
     * @param {Object} options 選項物件
     * [options.leading=false] (boolean): 指定在延遲開始前呼叫。
     * [options.maxWait] (number): 設定 func 允許被延遲的最大值。
     * [options.trailing=true] (boolean): 指定在延遲結束後呼叫。
     */
    export const debounce = function(wait,options = {}) {
      return客棧 function(target,descriptor) {
        descriptor.value = debounce(descriptor.value,options)
      }
    }

    封裝完之後,在元件中使用

    import {debounce} from '@/decorator'
    
    export default {
      methods:{
        @debounce(100)
        resize(){}
      }
    }

    2. loading

    在載入資料的時候,為了個使用者一個友好的提示,同時防止使用者繼續操作,一般會在請求前顯示一個loading,然後在請求結束之後關掉loading,一般寫法如下

    export default {
      methods:{
        async getData() {
          const loading = Toast.loading()
          try{
            const data = await loadData()
            // 其他操作
          }catch(error){
            // 異常處理
            Toast.fail('載入失敗');
          }finally{
            loading.clear()
          }  
        }
      }
    }

    我們可以把上面的loading的邏輯使用裝飾器重新封裝,如下程式碼

    import { Toast } from 'vant'
    
    /**
     * loading 裝飾器
     * @param {*} message 提示資訊
     * @param {function} errorFn 異常處理邏輯
     */
    export const loading =  function(message = '載入中...',errorFn = function() {}) {
      return function(target,descriptor) {
        const fn = descriptor.value
        descriptor.value = async function(...rest) {
          const loading = Toast.loading({
            message: message,forbidClick: true
          })
          try {
            return await fn.call(this,...rest)
          } catch (error) {
            // 在呼叫失敗,且使用者自定義失敗的回撥函式時,則執行
            errorFn && errorFn.call(this,error,...rest)
            console.error(error)
          } finally {
            loading.clear()
          }
        }
      }
    }

    然後改造上面的元件程式碼

    export default {
      methods:{
        @loading('載入中')
        async getData() {
          try{
            const data = await loadData()
            // 其他操作
          }catch(error){
            // 異常處理
            Toast.fail('載入失敗程式設計客棧');
          }  
        }
      }
    }

    3. 確認框

    當你點選刪除按鈕的時候,一般都需要彈出一個提示框讓使用者確認是否刪除,這時候常規寫法可能是這樣的

    import { Dialog } from 'vant'
    
    export default {
      methods: {
        deleteData() {
          Dialog.confirm({
            title: '提示',message: '確定要刪除資料,此操作不可回退。'
          }).then(() => {
            console.log('在這裡做刪除操作')
          })
        }
      }
    }

    我們可以把上面確認的過程提出來做成裝飾器,如下程式碼

    import { Dialog } from 'vant'
    
    /**
     * 確認提示框裝飾器
     * @param {*} message 提示資訊
     * @param {*} title 標題
     * @param {*} cancelFn 取消回撥函式
     */
    export function confirm(
      message = '確定要刪除資料,此操作不可回退。',title = '提示',cancelFn = function() {}
    ) {
      return function(target,descriptor) {
        const originFn = descriptor.value
        descriptor.value = async function(...rest) {
          try {
            await Dialog.confirm({
              message,title: title
            })
            originFn.apply(this,rest)
          } catch (error) {
            cancelFn && cancelFn(error)
          }
        }
      }
    }

    然後再使用確認框的時候,就可以這樣使用了

    export default {
      methods: {
        // 可以不傳參,使用預設引數
        @confirm()
        deleteData() {
          console.log('在這裡做刪除操作')
        }
      }
    }

    是不是瞬間簡單多了,當然還可以繼續封裝很多很多的裝飾器

    總結

    裝飾器用於將一段程式碼進行二次包裝。給程式碼增加一些行為操作和屬性。 使用裝飾器能大大減少程式碼的重複。增強程式碼可讀性。

    到此這篇關於Vue中使用裝飾器的文章就介紹到這了,更多相關Vue使用裝飾器內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!