最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Vue中$once的兩個(gè)實(shí)用小技巧分享

 更新時(shí)間:2022年04月27日 09:41:30   作者:江小皮  
$once是一個(gè)函數(shù),可以為Vue組件實(shí)例綁定一個(gè)自定義事件,但該事件只能被觸發(fā)一次,觸發(fā)之后隨即被移除,下面這篇文章主要給大家介紹了關(guān)于Vue中$once的兩個(gè)實(shí)用小技巧,需要的朋友可以參考下

前言

在 Vue 中有很多 API 都有很實(shí)用的地方,只是需要挖掘適用的場(chǎng)景,這里整理出了 $once 的兩個(gè)小技巧,也是在平常工作中用的比較多的,分享給大家,希望對(duì)大家能有幫助。

清除定時(shí)器

定時(shí)器大家用的應(yīng)該也不少,像我一開始一般都是這樣寫的,在 created 中創(chuàng)建定時(shí)器,在 beforeDestroy 中銷毀定時(shí)器。

<script>
export default {
  name: "Timer",
  data() {
    return {
      timer: null,
      count: 0,
    };
  },
  created() {
    this.timer = setInterval(() => {
      this.count++;
    }, 1000);
  },
  beforeDestroy() {
    clearInterval(this.timer);
  },
};
</script>

開始的時(shí)候也沒有發(fā)現(xiàn)有什么問題,沒啥毛病。

后面慢慢的了解了更多,才發(fā)現(xiàn)里面確實(shí)是有幾個(gè)問題存在的:

  • 定時(shí)器的創(chuàng)建和銷毀放在了兩個(gè)生命周期中,很容易就忘記在 beforeDestroy 中去銷毀,從而導(dǎo)致內(nèi)存的不必要消耗,并且可讀性太差了,后續(xù)維護(hù)變困難;
  • 如果定時(shí)器的創(chuàng)建和銷毀在同一個(gè)生命周期中的話,那么 timer 其實(shí)也就沒必要使用響應(yīng)式了,可以減少性能的浪費(fèi),直接在 created 中定義一個(gè)變量即可;
  • 在要銷毀的時(shí)候,只是清空了定時(shí)器,但是卻沒有把 timer 重置為 null,用完重置是個(gè)好習(xí)慣(定時(shí)器返回的值可以理解為這個(gè)定時(shí)器的 ID,通過這個(gè) ID 來(lái)銷毀這個(gè)定時(shí)器)。

優(yōu)化后的版本是這樣的,可讀性好了很多,有點(diǎn) composition API 那味兒了:),示例可以戳這里

export default {
  name: "OnceTimer",
  data() {
    return {
      count: 0,
    };
  },
  created() {
    let timer = setInterval(() => {
      this.count++;
    }, 1000);
    this.$once("hook:beforeDestroy", () => {
      clearInterval(timer);
      timer = null;
    });
  },
};

$once/$emit + async/await 實(shí)現(xiàn) Dialog 同步執(zhí)行

需求背景是這樣的:在全局有一個(gè)配置項(xiàng)showDialog,在點(diǎn)擊 查詢 的時(shí)候,如果這個(gè)配置項(xiàng)為 true,則需要 dialog 彈框讓用戶填寫一些數(shù)據(jù),當(dāng)這個(gè) dialog 彈框關(guān)閉之后,才能發(fā)出 confirm 的接口給后端,配置項(xiàng)為 false 時(shí),則直接發(fā)送 confirm 的請(qǐng)求。

這里會(huì)有兩個(gè)問題:

  • 這個(gè)彈框和 confirm 這個(gè)操作并不是強(qiáng)相關(guān),我不能把 confirm 的請(qǐng)求邏輯放置在 dialog 彈框里;
  • 當(dāng)控制彈框顯示的變量 visible 設(shè)為 true 時(shí),js 邏輯會(huì)繼續(xù)往下執(zhí)行,即把 confirm 的請(qǐng)求邏輯執(zhí)行完了,請(qǐng)求就發(fā)送出去了,這不是我想要的結(jié)果。

我們來(lái)模擬一下這個(gè)過程,如下圖所示:

在點(diǎn)擊查詢之后,先輸出了 form submit(用來(lái)模擬點(diǎn)擊查詢后的發(fā)出請(qǐng)求),然后在點(diǎn)擊 dialog 彈框的確定之后,才輸出了 dialog confirm??梢钥吹近c(diǎn)擊查詢的接口先發(fā)出,點(diǎn)擊 dialog 彈框 確認(rèn)的接口后發(fā)出。

解決這個(gè)問題可以從以下兩個(gè)方面入手:

  • dialog 的確認(rèn)邏輯 與 confirm 發(fā)送請(qǐng)求的邏輯要解耦,不能寫在一起,不利于復(fù)用
  • confirm 的發(fā)送請(qǐng)求邏輯,要等 dialog 關(guān)閉之后,才能執(zhí)行,那我們就需要知道 dialog 彈框是什么時(shí)候關(guān)閉的。

有了這兩點(diǎn)之后,就可以想到可以利用 $once/$emit + promise + async/ await 來(lái)實(shí)現(xiàn)這一邏輯。

通過 $once/$emit 來(lái)進(jìn)行通信,告知 dialog 關(guān)閉,通過 promise + async/ await 來(lái)使邏輯從異步變同步

我們來(lái)看下具體的代碼:

// dialog 組件
<template>
  <el-dialog
    title="提示"
    :visible.sync="dialogVisible"
    width="30%"
    :before-close="close"
  >
    <span>這是一段信息</span>
    <span slot="footer" class="dialog-footer">
      <el-button @click="close">取 消</el-button>
      <el-button type="primary" @click="confirm">確 定</el-button>
    </span>
  </el-dialog>
</template>

<script>
export default {
  props: ["dialogVisible"],
  data() {
    return {};
  },
  methods: {
    close() {
      this.$emit("before-dialog-close");
      this.$emit("update:dialogVisible", false);
    },
    confirm() {
      console.log("dialog confirm");
      this.close();
    },
  },
};
</script>
<template>
  <div>
    <el-form :inline="true" :model="formInline" class="demo-form-inline">
      <el-form-item label="審批人">
        <el-input v-model="formInline.user" placeholder="審批人"></el-input>
      </el-form-item>
      <el-form-item label="活動(dòng)區(qū)域">
        <el-select v-model="formInline.region" placeholder="活動(dòng)區(qū)域">
          <el-option label="區(qū)域一" value="shanghai"></el-option>
          <el-option label="區(qū)域二" value="beijing"></el-option>
        </el-select>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="onSubmit">查詢</el-button>
      </el-form-item>
    </el-form>
    <Dialog
      :dialogVisible.sync="visible"
      @before-dialog-close="() => this.$emit('beforeDialogClose')"
    />
  </div>
</template>
<script>
import Dialog from "./dialog";
export default {
  name: "Promise",
  components: {
    Dialog,
  },
  data() {
    return {
      formInline: {
        user: "",
        region: "",
      },
      // 控制 dialog 的展示
      visible: false,
      // 在業(yè)務(wù)中這是一個(gè)配置項(xiàng)
      showDialog: true,
    };
  },
  methods: {
    awaitDialogClose() {
      return new Promise((resolve) => {
        if (!this.visible) {
          resolve(null);
        }
        this.$once("beforeDialogClose", () => {
          resolve(null);
        });
      });
    },
    async onSubmit() {
      if (this.showDialog) {
        this.visible = true;
      }
      await this.awaitDialogClose();
      setTimeout(() => {
        console.log("form submit!");
      }, 1000);
    },
  },
};
</script>

效果如下:

在點(diǎn)擊查詢之后,我刻意的停留的一下,就是為了顯示點(diǎn)擊dialog確認(rèn)的邏輯點(diǎn)擊查詢的請(qǐng)發(fā)邏輯之前執(zhí)行。

詳細(xì)代碼具體分析,可以看到主要的邏輯就是在 dialog 關(guān)閉之前,$emit 出一個(gè)事件,來(lái)告訴父組件,dialog 要關(guān)閉了。

// dialog 組件
close() {
  // 通知父組件dialog要關(guān)閉了
  this.$emit("before-dialog-close");
  // 關(guān)閉 dialog
  this.$emit("update:dialogVisible", false);
},

在父組件中,創(chuàng)建一個(gè) promise,通過 $once 來(lái)等到 dialog 關(guān)閉的信號(hào) 。

// 發(fā)出信號(hào)
<Dialog
  :dialogVisible.sync="visible"
  @before-dialog-close="() => this.$emit('beforeDialogClose')"
/>
// 接收信號(hào)
awaitDialogClose() {
  return new Promise((resolve) => {
    // 當(dāng) dialog 沒彈框的時(shí)候,走這個(gè)邏輯,promise 直接結(jié)束
    if (!this.visible) {
      resolve(null);
    }
    // 當(dāng) dialog 要關(guān)閉的時(shí)候,$once 接收到了信號(hào),promise 結(jié)束
    this.$once("beforeDialogClose", () => {
      resolve(null);
    });
  });
},

在 confirm 的點(diǎn)擊邏輯中,用一個(gè) await 來(lái)保證 promsie 結(jié)束后,才往下繼續(xù)執(zhí)行。

async onSubmit() {
  // 當(dāng)配置為 true 時(shí),需要 dialog 彈框
  if (this.showDialog) {
    this.visible = true;
  }
  // promise 結(jié)束后,才會(huì)繼續(xù)往下執(zhí)行,否則就一直等待
  await this.awaitDialogClose();
  setTimeout(() => {
    console.log("form submit!");
  }, 1000);
},

至此,功能就完成了,這個(gè)功能適用場(chǎng)景還是很廣的(我也是請(qǐng)教了大佬才學(xué)會(huì)的),大家有興趣的也可以挖掘一些其他的使用場(chǎng)景。具體代碼在這里,有興趣的可以看一看呀。

可是在 Vue3 中,$once 被移除了,不過沒關(guān)系,Vue 官方也提出了可以替代的方法。

事件總線模式可以被替換為使用外部的、實(shí)現(xiàn)了事件觸發(fā)器接口的庫(kù),例如 mitttiny-emitter。

import emitter from 'tiny-emitter/instance'

export default {
  $once: (...args) =&gt; emitter.once(...args),
  $emit: (...args) =&gt; emitter.emit(...args),
}
復(fù)制代碼

總結(jié)

沒有無(wú)用的 API,只是沒有找到適用的場(chǎng)景。如果大家有更好的解決方法,也可以在評(píng)論區(qū)告訴我,讓我學(xué)習(xí)學(xué)習(xí)。

到此這篇關(guān)于Vue中$once實(shí)用小技巧的文章就介紹到這了,更多相關(guān)Vue $once小技巧內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Vue-cli中post請(qǐng)求發(fā)送Json格式數(shù)據(jù)方式

    Vue-cli中post請(qǐng)求發(fā)送Json格式數(shù)據(jù)方式

    這篇文章主要介紹了Vue-cli中post請(qǐng)求發(fā)送Json格式數(shù)據(jù)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-04-04
  • Vue 中如何正確引入第三方模塊的方法步驟

    Vue 中如何正確引入第三方模塊的方法步驟

    這篇文章主要介紹了Vue 中如何正確引入第三方模塊的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-05-05
  • 淺析Vue 防抖與節(jié)流的使用

    淺析Vue 防抖與節(jié)流的使用

    防抖節(jié)流就是使用定時(shí)器 來(lái)實(shí)現(xiàn)我們的目的。這篇文章通過實(shí)例代碼給大家介紹vue防抖與節(jié)流的使用,感興趣的朋友跟隨小編一起看看吧
    2019-11-11
  • Vuex的基本概念、項(xiàng)目搭建以及入坑點(diǎn)

    Vuex的基本概念、項(xiàng)目搭建以及入坑點(diǎn)

    Vuex是一個(gè)專門為Vue.js應(yīng)用程序開發(fā)的狀態(tài)管理模式,這篇文章主要介紹了Vuex的基本概念、項(xiàng)目搭建以及入坑點(diǎn),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-11-11
  • Vue3利用自定義指令進(jìn)行內(nèi)容控制的實(shí)現(xiàn)方法

    Vue3利用自定義指令進(jìn)行內(nèi)容控制的實(shí)現(xiàn)方法

    Vue3作為一個(gè)漸進(jìn)式JavaScript框架,提供了強(qiáng)大的自定義指令功能,使得權(quán)限控制變得既簡(jiǎn)單又高效,本文將詳細(xì)介紹如何在Vue3中使用自定義指令來(lái)判斷內(nèi)容是否顯示,以滿足不同用戶權(quán)限下的界面展示需求,需要的朋友可以參考下
    2024-04-04
  • vue數(shù)據(jù)監(jiān)聽解析Object.defineProperty與Proxy區(qū)別

    vue數(shù)據(jù)監(jiān)聽解析Object.defineProperty與Proxy區(qū)別

    這篇文章主要為大家介紹了vue數(shù)據(jù)監(jiān)聽解析Object.defineProperty Proxy源碼示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-03-03
  • vue使用highcharts自定義圖例點(diǎn)擊事件

    vue使用highcharts自定義圖例點(diǎn)擊事件

    這篇文章主要為大家詳細(xì)介紹了vue使用highcharts自定義圖例點(diǎn)擊事件,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • vue部署到線上為啥會(huì)出現(xiàn)404的原因分析及解決

    vue部署到線上為啥會(huì)出現(xiàn)404的原因分析及解決

    這篇文章主要介紹了vue部署到線上為啥會(huì)出現(xiàn)404的原因分析及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-04-04
  • 使用vue-cli+webpack搭建vue開發(fā)環(huán)境的方法

    使用vue-cli+webpack搭建vue開發(fā)環(huán)境的方法

    這篇文章主要介紹了使用vue-cli+webpack搭建vue開發(fā)環(huán)境的方法,需要的朋友可以參考下
    2017-12-12
  • Vue的路由配置過程(Vue2和Vue3的路由配置)

    Vue的路由配置過程(Vue2和Vue3的路由配置)

    這篇文章回顧了Vue2和Vue3中路由的配置步驟,包括安裝正確的路由版本、創(chuàng)建路由實(shí)例、配置routes以及在入口文件中注冊(cè)路由,Vue2中使用Vue.use(VueRouter),而Vue3中使用createRouter和createWebHashHistory
    2025-01-01

最新評(píng)論

威远县| 香港| 调兵山市| 合水县| 宣武区| 温泉县| 蓬安县| 文安县| 桐庐县| 长寿区| 瑞昌市| 阿克苏市| 庆元县| 勐海县| 武穴市| 额尔古纳市| 囊谦县| 南郑县| 类乌齐县| 永州市| 滕州市| 拉萨市| 大石桥市| 红河县| 东城区| 拉孜县| 辉南县| 禹城市| 三穗县| 淮南市| 肇东市| 梅河口市| 呼玛县| 封开县| 门头沟区| 门源| 南漳县| 开平市| 邻水| 名山县| 焦作市|