欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

vue中的eventBus會(huì)不會(huì)產(chǎn)生內(nèi)存泄漏你知道嗎

 更新時(shí)間:2022年02月11日 10:59:24   作者:凡人進(jìn)階  
這篇文章主要為大家詳細(xì)介紹了vue中的eventBus會(huì)不會(huì)產(chǎn)生內(nèi)存泄漏,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助

eventBus是在vue中經(jīng)常用來(lái)解決跨組件消息傳遞的問(wèn)題,但對(duì)它的使用要特別注意,否則會(huì)產(chǎn)生很?chē)?yán)重的后果。

引入

本文介紹了eventBus的實(shí)現(xiàn)原理,并介紹它如何在vue中使用,并舉了一個(gè)具體的例子來(lái)說(shuō)明,如果使用不當(dāng),它會(huì)造成內(nèi)存泄漏。

要注意eventBus并不是前端的概念。

由greenrobot [1] 組織貢獻(xiàn)(該組織還貢獻(xiàn)了greenDAO),一個(gè)Android事件發(fā)布/訂閱輕量級(jí)框架,

功能:通過(guò)解耦發(fā)布者和訂閱者簡(jiǎn)化Android事件傳遞 [2]

EventBus可以代替Android傳統(tǒng)的Intent,Handler,Broadcast或接口函數(shù),在Fragment,Activity,Service線(xiàn)程之間傳遞數(shù)據(jù),執(zhí)行方法。

特點(diǎn):代碼簡(jiǎn)潔,是一種發(fā)布訂閱設(shè)計(jì)模式(觀(guān)察者設(shè)計(jì)模式)。

內(nèi)容

  • eventBus在vue中的實(shí)現(xiàn);
  • 在vue使用eventBus;
  • 使用不當(dāng)?shù)膯?wèn)題:多次執(zhí)行回調(diào);內(nèi)存泄漏;
  • 解決方案:及時(shí)調(diào)用$off

eventBus在vue中的實(shí)現(xiàn)

eventBus是事件總線(xiàn)的意思,它本質(zhì)上是一個(gè)發(fā)布訂閱者實(shí)現(xiàn),在vue2.X中,vue實(shí)例上提供了$on,$emit,$off這三個(gè)方法,分別用來(lái)添加觀(guān)察者,發(fā)布事件,取消訂閱這三個(gè)操作。

所以,我們可以直接把一個(gè)vue實(shí)例掛到Vue的原型上來(lái)充當(dāng)組件相互通信的中介。

Vue.prototype.$eventBus = new Vue()

這樣一來(lái),所有的Vue組件都可以沿著原型鏈找到這個(gè)$eventBus,從而訪(fǎng)問(wèn)$on, $off,$emit。

它可以幫助我們實(shí)現(xiàn)跨組件的通信。

例子:使用eventBus

在根組件中發(fā)布事件,在兩個(gè)子組件中去監(jiān)聽(tīng)事件。

<div id="app">
? ?<h2>eventBus的基本使用</h2>
? ?<com1></com1>
? ?<com2></com2>
?</div>
?<script>
? ?Vue.prototype.$eventBus = new Vue()
? ?Vue.component('com1', {
? ? ?template:`<div>com1</div>`,
? ? ?created () {
? ? ? ?this.$eventBus.$on('event1', function f1(d){
? ? ? ? ?conse.log(d, 'com1 listen...  event1')
? ? ?  })
? ?  },
?  })
? ?Vue.component('com2', {
? ? ?template:`<div>com2</div>`,
? ? ?created () {
? ? ? ?this.$eventBus.$on('event2', function f2(d) {
? ? ? ? ?conse.log(d, 'com2 listen...  event2')
? ? ?  })
? ?  }
?  })
? ?var vm = new Vue({
? ? ?el: '#app',
? ? ?created () {
? ? ? ?setInterval( () => {
? ? ? ? ?const d = Date.now()
? ? ? ? ?this.$eventBus.$emit('event1', d)
? ? ? ? ?this.$eventBus.$emit('event2', d)
? ? ?  }, 3000)
? ?  }
?  })
?</script>

在創(chuàng)建com1組件時(shí),訂閱event1事件;在創(chuàng)建com2組件時(shí),訂閱event2事件;在創(chuàng)建根組件(vue實(shí)例)時(shí),開(kāi)啟定時(shí)器:每隔3s發(fā)布事件,這樣的話(huà),com1和com2就都可以收到事件,并執(zhí)行對(duì)應(yīng)的回調(diào)。

效果如下:

 

例子:不及時(shí)取消訂閱

如果不及時(shí)取消訂閱,則回調(diào)函數(shù)仍會(huì)執(zhí)行,更嚴(yán)重的是,如果在事件處理回調(diào)函數(shù)中引用了外部變量形成了閉包,則會(huì)導(dǎo)致內(nèi)存泄漏。

下面的代碼說(shuō)明這個(gè)問(wèn)題。

在根組件(vue實(shí)例)中,補(bǔ)充一個(gè)數(shù)據(jù)項(xiàng)showCom1,并配置v-if指令來(lái)實(shí)現(xiàn)銷(xiāo)毀和重建com1組件。

<div id="app">
? ?<h2>不及時(shí)取消訂閱的問(wèn)題</h2>
? ?<button @click="showCom1=!showCom1">
? ?  {{showCom1 ? "銷(xiāo)毀" : "重建"}}組件1
? ?</button>
? ?<com1 v-if="showCom1"></com1>
? ?<com2></com2>
?</div>
?<script>
? ?Vue.prototype.$eventBus = new Vue()
? ?Vue.component('com1', {
? ? ?template:`<div>com1</div>`,
? ? ?created () {
? ? ? ?conse.log('創(chuàng)建com1')
? ? ? ?this.$eventBus.$on('event1', function f1(d) {
? ? ? ? ?conse.log(d, 'com1 listen... event1')
? ? ?  })
? ?  }
?  })
? ?Vue.component('com2', {
? ? ?template:`<div>com2</div>`,
? ? ?created () {
? ? ? ?this.$eventBus.$on('event2', function f2(d) {
? ? ? ? ?conse.log(d, 'com2 listen... event2')
? ? ?  })
? ?  }
?  })
? ?var vm = new Vue({
? ? ?el: '#app',
? ? ?data:{
? ? ? ?showCom1: true
? ?  },
? ? ?created () {
? ? ? ?setInterval( () => {
? ? ? ? ?const d = Date.now()
? ? ? ? ?this.$eventBus.$emit('event1', d)
? ? ? ? ?this.$eventBus.$emit('event2', d)
? ? ?  }, 3000)
? ?  }
?  })
?</script>

先提一個(gè)問(wèn)題:你覺(jué)得com1組件被銷(xiāo)毀后,它在created中訂閱的event1事件還能再收到嗎?對(duì)應(yīng)的回調(diào)函數(shù)還能再執(zhí)行嗎?一般的想法是組件都銷(xiāo)毀了,那它訂閱的事件肯定也收不到了嘛。

答案是:還能收到。原因很簡(jiǎn)單:事件訂閱這功能是$eventBus對(duì)象完成的,與這個(gè)com1組件無(wú)關(guān)。

上面的代碼執(zhí)行的效果,是這樣的:

  • 銷(xiāo)毀組件1之后,它還能正常收到event1事件,并執(zhí)行回調(diào);
  • 再次創(chuàng)建組件1后,它會(huì)再次訂閱event1事件,所以結(jié)果是執(zhí)行兩次回調(diào)。

下面再來(lái)說(shuō)明內(nèi)存泄漏的問(wèn)題,把com1的組件內(nèi)容改成如下:

 Vue.component('com1', {
   template:`<div>com1</div>`,
   created () {
     console.log('創(chuàng)建com1')
     let m = 1*1024 * 1024
     let arr = new Array(m).fill('a')
 
     this.$eventBus.$on('event1', function f1(d) {
       // 注意這里有一個(gè)閉包
       console.log(d, 'com1 listen... event1', arr[1])
    })
  }
 })

在回調(diào)函數(shù)f1中引用函數(shù)之外的變量arr,這里有一個(gè)閉包。

下面在瀏覽器的調(diào)試工具中的memory添加一個(gè)快照,查看結(jié)果如下:

然后,點(diǎn)擊頁(yè)面上的“銷(xiāo)毀組件1”,再次添加一個(gè)快照,你會(huì)發(fā)現(xiàn)這個(gè)空間并沒(méi)有釋放掉。

解釋如下:

 

上面是這個(gè)過(guò)程的示意圖,由于沒(méi)有及時(shí)取消訂閱f1,所以arr這個(gè)數(shù)組并沒(méi)有釋放掉。

 

解決方案:

在com1的destoryed鉤子中,調(diào)用$off來(lái)取消訂閱。

destroyed () {
? ?// 取消所有對(duì)event1事件的監(jiān)聽(tīng)
? ?this.$eventBus.$off('event1')
?}

調(diào)試結(jié)果如下:

可見(jiàn),com1刪除之后,這個(gè)數(shù)值的空間釋放掉了,同時(shí)它的事件監(jiān)聽(tīng)函數(shù)也不會(huì)再執(zhí)行了。

其它注意事項(xiàng)

$off的格式:

  • $off() 會(huì)取消所有的事件訂閱;
  • $off('事件名') 會(huì)取消指定事件名的;
  • $off('事件名', 回調(diào)) 會(huì)取消指定事件名的,指定回調(diào)

父子組件的created和mounted的區(qū)別, 按執(zhí)行順序:

  • 父組件的created 先于子組件的created
  • 父組件的mounted先于子組件的mounted

所以,到底在哪個(gè)鉤子中訂閱,在哪個(gè)鉤子中發(fā)布,要根據(jù)情況來(lái)定。

總結(jié)

eventBus是一個(gè)名詞,并非前端獨(dú)有;

new Vue() 得到的實(shí)例上已經(jīng)實(shí)現(xiàn)了發(fā)布訂閱模式,可以直接做eventBus使用;

使用eventBus要及時(shí)調(diào)用$off;

本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!     

相關(guān)文章

  • vue.js實(shí)現(xiàn)雙擊放大預(yù)覽功能

    vue.js實(shí)現(xiàn)雙擊放大預(yù)覽功能

    這篇文章主要為大家詳細(xì)介紹了vue.js實(shí)現(xiàn)雙擊放大預(yù)覽功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-06-06
  • 在Vue3中使用CodeMirror插件的方法詳解

    在Vue3中使用CodeMirror插件的方法詳解

    CodeMirror是一個(gè)功能強(qiáng)大的Web代碼編輯器,廣泛應(yīng)用于各種Web應(yīng)用中,在Vue3項(xiàng)目中集成CodeMirror,可以顯著提升代碼編輯和展示的用戶(hù)體驗(yàn),本文將結(jié)合實(shí)際案例,詳細(xì)介紹在Vue3中使用CodeMirror插件的方法,需要的朋友可以參考下
    2024-12-12
  • 前端vue項(xiàng)目如何使用Decimal.js做加減乘除求余運(yùn)算

    前端vue項(xiàng)目如何使用Decimal.js做加減乘除求余運(yùn)算

    decimal.js是使用的二進(jìn)制來(lái)計(jì)算的,可以更好地實(shí)現(xiàn)格化式數(shù)學(xué)運(yùn)算,對(duì)數(shù)字進(jìn)行高精度處理,使用decimal類(lèi)型處理數(shù)據(jù)可以保證數(shù)據(jù)計(jì)算更為精確,這篇文章主要給大家介紹了關(guān)于前端vue項(xiàng)目如何使用Decimal.js做加減乘除求余運(yùn)算的相關(guān)資料,需要的朋友可以參考下
    2024-05-05
  • 詳解如何使用Vue2做服務(wù)端渲染

    詳解如何使用Vue2做服務(wù)端渲染

    本篇文章主要介紹了如何使用Vue2做服務(wù)端渲染 ,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-03-03
  • VUE+Canvas實(shí)現(xiàn)財(cái)神爺接元寶小游戲

    VUE+Canvas實(shí)現(xiàn)財(cái)神爺接元寶小游戲

    這篇文章主要介紹了VUE+Canvas實(shí)現(xiàn)財(cái)神爺接元寶小游戲,需要的朋友可以參考下本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2021-04-04
  • 詳解windows下vue-cli及webpack 構(gòu)建網(wǎng)站(四) 路由vue-router的使用

    詳解windows下vue-cli及webpack 構(gòu)建網(wǎng)站(四) 路由vue-router的使用

    本篇文章主要介紹了windows下vue-cli及webpack 構(gòu)建網(wǎng)站(四) 路由vue-router的使用,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-06-06
  • vue之如何配置默認(rèn)顯示頁(yè)面和默認(rèn)路由

    vue之如何配置默認(rèn)顯示頁(yè)面和默認(rèn)路由

    這篇文章主要介紹了vue之如何配置默認(rèn)顯示頁(yè)面和默認(rèn)路由問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • 詳解vue引入子組件方法

    詳解vue引入子組件方法

    在本文中小編給大家分享的是關(guān)于vue引入子組件方法和先關(guān)注意點(diǎn),有需要的朋友們可以學(xué)習(xí)下。
    2019-02-02
  • 淺析vue數(shù)據(jù)綁定

    淺析vue數(shù)據(jù)綁定

    本文主要介紹了vue數(shù)據(jù)綁定的相關(guān)知識(shí),具有一定的參考價(jià)值,下面跟著小編一起來(lái)看下吧
    2017-01-01
  • 在vue.js中抽出公共代碼的方法示例

    在vue.js中抽出公共代碼的方法示例

    這篇文章主要給大家介紹了在vue.js中抽出公共代碼的方法,文中給出了詳細(xì)的示例代碼供大家參考學(xué)習(xí),對(duì)大家具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起看看吧。
    2017-06-06

最新評(píng)論