<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          三步帶你玩轉前端裝飾器

          共 14472字,需瀏覽 29分鐘

           ·

          2021-11-05 14:51

          作者:CoolLsk
          來源:SegmentFault 思否社區(qū)

          • 什么是裝飾器
          • 裝飾器怎么封裝
          • 裝飾器能干啥

          1、什么是裝飾器

          看個例子就懂了eg:
          正常開發(fā)是這樣的:
              1、先定義節(jié)流方法:
                  methods: {
                    throttle (func, delay) {            
                        var timer = null;            
                        return function() {                
                            var context = this;               
                            var args = arguments;                
                            if (!timer) {                    
                                timer = setTimeout(function() {             
                                    func.apply(context, args);               
                                    timer = null;                    
                                }, delay);                
                            }            
                        }        
                    }    
                  }
                  2、然后執(zhí)行A方法:
                  methods: {
                       a() {
                          this.throttle(()=>{
                           //執(zhí)行業(yè)務邏輯
                          }, 400)
                      }
                  }

          反正就是各種嵌套,看起來代碼很膿腫,接下來看看【裝飾器】怎么寫↓

          //使用裝飾器過后的寫法
          import { throttle} from "@/utils/decorator";

          methods: {
            @throttle(400)  // 裝飾器(節(jié)流)  
            a() {
              // 執(zhí)行業(yè)務邏輯
              //此時會發(fā)現點擊效果跟上面寫法一樣
              console.log('執(zhí)行業(yè)務')
            },
          }

          現在看到的寫法是不是涼快了很多,沒有多層嵌套

          2、裝飾器怎么封裝

          1、在工具文件創(chuàng)建decorator.js
              // utils/decorator.js
              /**
               * 節(jié)流,一定時間內,只能觸發(fā)一次操作
               * @export
               * @param {Function} fn - 運行函數
               * @param {Number} wait - 延遲時間
               * @returns
               */
              export function throttle(wait = 2000) {
                //返回值:被傳遞給函數的對象。    
                return function(target, name, descriptor) {
                  // @param target 類本身
                  // @param name 裝飾的屬性(方法)名稱
                  // @param descriptor 屬性(方法)的描述對象
                  const fn = descriptor.value 
                  let canRun = true
                  descriptor.value = async function(...args) {
                    //具體的裝飾器業(yè)務在這里面編寫    
                    if (!canRun) return
                    await fn.apply(this, args) // 執(zhí)行業(yè)務下的方法
                    canRun = false
                    setTimeout(() => {
                      canRun = true
                    }, wait)
                  }
                }
              }
              2、在業(yè)務板塊里面聲明使用
                 methods: {
                    @throttle(400)  // 裝飾器(節(jié)流)  
                    a() {
                      // 執(zhí)行業(yè)務邏輯
                      //此時會發(fā)現點擊效果跟上面寫法一樣
                      console.log('執(zhí)行業(yè)務')
                    },
                  }
              //現在看到代碼是不是就沒有那么膿腫了,就一行指令

          3、裝飾器能干啥

          現實開發(fā)中經常遇到節(jié)流,防抖,日志,按鈕權限等等一些業(yè)務執(zhí)行之前的攔截操作

          以下是我平時使用的一些裝飾器,希望對看到這里的你有幫助!

          // utils/decorator.js
          import { Dialog } from 'vant';

          /**
           * loading 開關裝飾器
           * @param {String} loading 當前頁面控制開關的變量名字
           * @param {Function} errorCb 請求異常的回調 返回error 一般不用寫
           * 如果 errorCb 為 function 為你綁定 this  如果是箭頭函數 則第二個參數為this
           * @example
           * @loading('pageLoading',function(){that.demo = '123123'})
           * async getTable(){
           *  this.table =  this.$apis.demo()
           * }
           * @example
           * @loading('pageLoading',(error,that)=>{that.demo = '123123'})
           * async getTable(){
           *  this.table =  this.$apis.demo()
           * }
           */
          export function loading (loading, errorCb = Function.prototype) {
            return function (target, name, descriptor) {
              const oldFn = descriptor.value;
              descriptor.value = async function (...args) {
                try {
                  this[loading] = true;
                  await oldFn.apply(this, args);
                } catch (error) {
                  errorCb.call(this, error, this);
                } finally {
                  this[loading] = false;
                }
              };
            };
          }

          /**
           * 日志注入
           * @export
           * @param {Function} fn - 運行函數
           * @param {data} 日志需要的參數
           * @returns
           */
          export function log(data) {
            return function(target, name, descriptor) {
              const fn = descriptor.value;
              descriptor.value = async function(...args) {
                await logApi(data) // 自己的日志接口
                await fn.apply(this, args);
              }
            }
          }

          // utils/decorator.js
          /**
           * 節(jié)流,一定時間內,只能觸發(fā)一次操作
           * @export
           * @param {Function} fn - 運行函數
           * @param {Number} wait - 延遲時間
           * @returns
           */
          export function throttle(wait= 2000) {
            return function(target, name, descriptor) {
              const fn = descriptor.value
              let canRun = true
              descriptor.value = async function(...args) {
                if (!canRun) return
                await fn.apply(this, args)
                canRun = false
                setTimeout(() => {
                  canRun = true
                }, wait)
              }
            }
          }
          // utils/decorator.js
          /**
           * 防抖,連續(xù)操作時,只在最后一次觸發(fā)
           * @export
           * @param {Function} fun - 運行函數
           * @param {Number} wait - 延遲時間
           * @returns
           */
          export function debounce(wait= 2000) {
            return function(target, name, descriptor) {
              const fn = descriptor.value
              let timer = null
              descriptor.value = function(...args) {
                const _this = this._isVue ? this : target
                clearTimeout(timer)
                timer = setTimeout(() => {
                  fn.apply(_this, args)
                }, wait)
              }
            }
          }
          /**
           * 表單校驗
           * @param {String} formElKey - 表單el
           */
          export const formValidation = (formElKey = 'formEl') => {
            return (target, name, descriptor) => {
              const method = descriptor.value
              descriptor.value = async function() {
                const _this = this._isVue ? this : target
                const isValidate = _this[formElKey]?.validate
                if (isValidate) {
                  const [, res] = await to(isValidate())
                  if (!res) return false
                }
                return method.apply(_this, arguments)
              }
            }
          }
          // utils/decorator.js
          /**
           * 確認框
           * @param {String} title - 標題
           * @param {String} concent - 內容
           * @param {String} confirmButtonText - 確認按鈕名稱
           * @returns
           */
          export const alertDecorator = ({title = '提示', message = '請輸入彈窗內容', confirmButtonText = '我知道了'}) => {
            return (target, name, descriptor) => {
              const fn = descriptor.value;
              descriptor.value = function (...args) {
                  Dialog.alert({title, message, confirmButtonText}).then(() => {
                    fn.apply(this, args);
                  });
              }
            }
          }



          /**
           * 緩存計算結果
           * @export
           * @param {Function} fn
           * @returns
           */
          export function cached() {
            return function(target, name, descriptor) {
              const method = descriptor.value
              const cache = new Map()
              descriptor.value = function() {
                const _this = this._isVue ? this : target
                const key = JSON.stringify(arguments)
                if (!cache.has(key)) {
                  cache.set(key, method.apply(_this, arguments))
                }
                return cache.get(key)
              }
            }
          }
          既然看到了這里,先收藏一下,如果實戰(zhàn)劃水時間提高了,別忘了回來點個贊哦
          如果覺得有用,就分享給你的小伙伴吧!接下來就是快樂的劃水了 O(∩_∩)O哈哈~


          點擊左下角閱讀原文,到 SegmentFault 思否社區(qū) 和文章作者展開更多互動和交流,掃描下方”二維碼“或在“公眾號后臺回復“ 入群 ”即可加入我們的技術交流群,收獲更多的技術文章~

          - END -


          瀏覽 71
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  黄色AV网探花 | 亚洲精品一二三四五区 | 一本色道久久综合亚洲精东小说 | 久久久久久久久国产精品视频 | 熟女天堂 |