<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>

          活用async/await,實現(xiàn)一些讓Vue更好用的裝飾器

          共 11379字,需瀏覽 23分鐘

           ·

          2021-09-12 08:58

          點擊上方 前端瓶子君,關(guān)注公眾號

          回復(fù)算法,加入前端編程面試算法每日一題群

          Async/await加上裝飾器,會產(chǎn)生神奇的效果。

          以下所列幾個裝飾器,都要求被裝飾的方法寫成async/await,

          這樣就可以利用async/await本身的特性,從方法外部得知異步方法是否運行完成。

          于是便實現(xiàn)了將繁雜和麻煩的邏輯隱藏在裝飾器內(nèi)部,使業(yè)務(wù)代碼更加干凈。

          以下裝飾器除了最后一個都是用在Typescript環(huán)境下的class寫法的vue里的。

          最后一個其實并不是裝飾器,而是一個高階函數(shù),但是眾所周知,裝飾器本質(zhì)上就是個高階函數(shù)。

          所以所有裝飾器都可以很容易的改成高階函數(shù),然后用在js環(huán)境的vue里。

          給vue添加一個指示初始化完成的變量。

          1. 使用場景舉例:

            搜索頁面:搜索中顯示loading,結(jié)果為空時顯示暫無數(shù)據(jù)。

            第一次打開頁面時,在created或者mounted中發(fā)出請求,進行初始化的搜索,此時搜索還沒完成,顯示暫無數(shù)據(jù)并不合適。
            這個時候就需要一個變量來判斷頁面是不是第一次打開。

          2. 代碼解釋:

            通過裝飾器添加這個屬性(pageIsReady)到組件的類上,

            并包裝vue的created, mounted和beforeDestroy方法,監(jiān)控組件的生命周期。
            當(dāng)created或者mounted里發(fā)出的請求完成后,就把pageIsReady設(shè)為true。
            然后在beforeDestroy中重置狀態(tài),因為裝飾器用了閉包,只會實例化一次。

          import { Constructor } from "vue/types/options";
          export type WrapReadyProperty<T> = T & {
              pageIsReady?: boolean;
              createdDone?: boolean;
              mountedDone?: boolean
          }
          /**  
           * 在@compontent 之后使用這個裝飾器,
           * 組件就會被注入屬性 pageIsReady,
           * 當(dāng)created和mounted都執(zhí)行完成時 pageIsReady 變成true,
           * 要求mounted或created是async/await。(取決于在哪個方法中發(fā)請求初始化組件)
           * 然后可以在template中直接使用。
           * 在script中使用調(diào)用isPageReady.call(this)方法;
              */

          export default function PageReadyStatus() {
              return function pageReadyEnhancement<T extends WrapReadyProperty<Constructor>>(target: T{
                  const oldMounted = target.prototype.mounted || function() { }
                  const oldCreated = target.prototype.created || function() { }
                  const oldBeforeDestroy = target.prototype.beforeDestroy || function() { }
                  target.prototype.pageIsReady = false;
                  function isCreatedMountedAllDone(this: T{
                      return !!this.createdDone && !!this.mountedDone;
                  }
                  target.prototype.created = async function(...params: any[]{
                      await oldCreated.apply(this, params);
                      this.createdDone = true;
                      this.pageIsReady = isCreatedMountedAllDone.call(this)
                  }
                  target.prototype.mounted = async function(...params: any[]{
                      await oldMounted.apply(this, params);
                      this.mountedDone = true
                      this.pageIsReady = isCreatedMountedAllDone.call(this)
                  }
                  target.prototype.beforeDestroy = async function(...params: any[]{
                      await oldBeforeDestroy.apply(this, params);
                      this.createdDone = false;
                      this.mountedDone = true
                      this.pageIsReady = false;
                  }
                  return target
              };
          }

          export function isPageReady(this: WrapReadyProperty<Vue>{
              return this.pageIsReady

          給事件回調(diào)函數(shù)和按鈕Dom添加防抖與loading樣式

          1. 使用場景舉例:

            點擊一個按鈕,觸發(fā)一個函數(shù),并發(fā)出一個請求。此時需要給這個函數(shù)防抖,并給按鈕增加一個loading的樣式

          2. 代碼解釋

            利用async/await把異步變成同步的特性,在裝飾器中發(fā)現(xiàn)方法還沒執(zhí)行完成時直接返回。

            并從時間對象中拿到按鈕的dom節(jié)點,改變按鈕的樣式。我這里是用了一個cursor:wait;

          /*
           * 請保證被包裝的方法的參數(shù)列表最后一個是點擊事件的參數(shù)
           */

          export default function buttonThrottle() {
              let pending = false;
              return function(target: any, name: string): any {
                  const btnClickFunc = target[name];
                  const newFunc = async function(this: Vue, ...params: any[]{
                      if (pending) {
                          return;
                      }
                      const event:Event = params[params.length - 1];
                      let btn = event.target as HTMLElement
                      pending = true;
                      const recoverCursor = changeCursor(btn);
                      try {
                          await btnClickFunc.apply(this, params);
                      } catch (error) {
                          console.error(error);
                      }
                      recoverCursor();
                      pending = false;
                  };
                  target[name] = newFunc;
                  return target;
              };
          }
          function changeCursor(btn?: HTMLElement{
              if (btn == null) {
                  return () => {};
              }
              const oldCursor = btn.style.cursor;
              btn.style.cursor = "wait";
              return () => {
                  btn.style.cursor = oldCursor;
              };

          1. 用法:
            在點擊事件函數(shù)上使用這個裝飾器.
           import { Component, Vue } from "vue-property-decorator";
              import buttonThrottle from "@/ui/view/utils/buttonThrottle";


              type Member = { account_no: string; name: string; warn?: string };
              @Component({ components: {} })
              export default class AddMemberInput extends Vue {
              @buttonThrottle()
              private async confirmAdd() {
                  await this.addMembers(this.getVaildMembers());
                  }    
              }

          注入loading變量

          1. 場景

            發(fā)請求時在頁面上加一個loading的狀態(tài),比如element-ui里就有一個v-loading的指令。

            這個指令需要一個是否在loading中的變量

          2. 代碼解釋

            往組件上增加一個變量,變量名由參數(shù)variableName指定

            該變量會在被包裝的方法執(zhí)行期間為true

            這樣就不用自己寫this.loading=true this.loading=false了

           export default function FunctionLoadingVariable(variableName: string{
                 return function(target: any, name: string): any {
                     target[variableName] = false;
                     const btnClickFunc = target[name];
                     const newFunc = async function(this: Vue & {
                         [key: string]: boolean
                     }, ...params: any[]
          {
                         try {
                             this[variableName] = true
                             await btnClickFunc.apply(this, params);
                         } catch (error) {
                             console.error(error);
                         }
                         this[variableName] = false
                     };
                     target[name] = newFunc;
                     return target;
                 };
             } 

          mounted之前顯示白屏

          1. 場景

            頁面加載的過程很丑,所以可以在mouted之前顯示白屏,或者弄一個骨架屏。

            特別是在微信小程序中,因為加載完成之前特別丑,所以幾乎所有小程序都會在mounted之前白屏。

          2. 通過async/await獲得mounted或者created是否執(zhí)行完成
            再通過指向vue實力的this拿到組件根節(jié)點,然后按需修改它
            以下代碼只是將組件隱藏了,實際上可以寫更復(fù)雜的邏輯,在加載過程中顯示其他內(nèi)容,畢竟拿到了Dom,想干嘛就干嘛。

           function firstPaintControl(vueObj{
              let oldMounted = vueObj.mounted || function() {};
              vueObj.mounted = async function(...params{
                this.$el.style.visibility = 'hidden';
                await oldMounted.apply(this, params);
                this.$el.style.visibility = 'visible';
              };
              return vueObj;
            }

          關(guān)于本文

          來源:OLong

          https://segmentfault.com/a/1190000037604556

          最后

          歡迎關(guān)注【前端瓶子君】??ヽ(°▽°)ノ?
          回復(fù)「算法」,加入前端編程源碼算法群,每日一道面試題(工作日),第二天瓶子君都會很認真的解答喲!
          回復(fù)「交流」,吹吹水、聊聊技術(shù)、吐吐槽!
          回復(fù)「閱讀」,每日刷刷高質(zhì)量好文!
          如果這篇文章對你有幫助,在看」是最大的支持
           》》面試官也在看的算法資料《《
          “在看和轉(zhuǎn)發(fā)”就是最大的支持
          瀏覽 105
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

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

          手機掃一掃分享

          分享
          舉報
          <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>
                  操逼香蕉 | 少妇被操| 人妻天天爽 | 日日天天干 | 五月婷婷久久怎么了呀 |