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

vue中的eventBus會不會產生內存泄漏你知道嗎

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

eventBus是在vue中經常用來解決跨組件消息傳遞的問題,但對它的使用要特別注意,否則會產生很嚴重的后果。

引入

本文介紹了eventBus的實現(xiàn)原理,并介紹它如何在vue中使用,并舉了一個具體的例子來說明,如果使用不當,它會造成內存泄漏。

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

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

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

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

特點:代碼簡潔,是一種發(fā)布訂閱設計模式(觀察者設計模式)。

內容

  • eventBus在vue中的實現(xiàn);
  • 在vue使用eventBus;
  • 使用不當的問題:多次執(zhí)行回調;內存泄漏;
  • 解決方案:及時調用$off

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

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

所以,我們可以直接把一個vue實例掛到Vue的原型上來充當組件相互通信的中介。

Vue.prototype.$eventBus = new Vue()

這樣一來,所有的Vue組件都可以沿著原型鏈找到這個$eventBus,從而訪問$on, $off,$emit。

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

例子:使用eventBus

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

<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組件時,訂閱event1事件;在創(chuàng)建com2組件時,訂閱event2事件;在創(chuàng)建根組件(vue實例)時,開啟定時器:每隔3s發(fā)布事件,這樣的話,com1和com2就都可以收到事件,并執(zhí)行對應的回調。

效果如下:

 

例子:不及時取消訂閱

如果不及時取消訂閱,則回調函數仍會執(zhí)行,更嚴重的是,如果在事件處理回調函數中引用了外部變量形成了閉包,則會導致內存泄漏。

下面的代碼說明這個問題。

在根組件(vue實例)中,補充一個數據項showCom1,并配置v-if指令來實現(xiàn)銷毀和重建com1組件。

<div id="app">
? ?<h2>不及時取消訂閱的問題</h2>
? ?<button @click="showCom1=!showCom1">
? ?  {{showCom1 ? "銷毀" : "重建"}}組件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>

先提一個問題:你覺得com1組件被銷毀后,它在created中訂閱的event1事件還能再收到嗎?對應的回調函數還能再執(zhí)行嗎?一般的想法是組件都銷毀了,那它訂閱的事件肯定也收不到了嘛。

答案是:還能收到。原因很簡單:事件訂閱這功能是$eventBus對象完成的,與這個com1組件無關。

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

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

下面再來說明內存泄漏的問題,把com1的組件內容改成如下:

 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) {
       // 注意這里有一個閉包
       console.log(d, 'com1 listen... event1', arr[1])
    })
  }
 })

在回調函數f1中引用函數之外的變量arr,這里有一個閉包。

下面在瀏覽器的調試工具中的memory添加一個快照,查看結果如下:

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

解釋如下:

 

上面是這個過程的示意圖,由于沒有及時取消訂閱f1,所以arr這個數組并沒有釋放掉。

 

解決方案:

在com1的destoryed鉤子中,調用$off來取消訂閱。

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

調試結果如下:

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

其它注意事項

$off的格式:

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

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

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

所以,到底在哪個鉤子中訂閱,在哪個鉤子中發(fā)布,要根據情況來定。

總結

eventBus是一個名詞,并非前端獨有;

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

使用eventBus要及時調用$off;

本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關注腳本之家的更多內容!     

相關文章

  • vue的for循環(huán)使用方法

    vue的for循環(huán)使用方法

    在本篇文章里小編給大家整理了關于vue的for循環(huán)使用方法和步驟,有需要的朋友們跟著學習下。
    2019-02-02
  • vue實現(xiàn)樹形菜單效果

    vue實現(xiàn)樹形菜單效果

    這篇文章主要為大家詳細介紹了vue實現(xiàn)樹形菜單效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-03-03
  • vue 行為驗證碼之滑動驗證AJ-Captcha使用詳解

    vue 行為驗證碼之滑動驗證AJ-Captcha使用詳解

    這篇文章主要介紹了vue 行為驗證碼之滑動驗證AJ-Captcha使用詳解,AJ-Captcha不需要npm安裝,只需要將組件 verifition復制到所使用的components目錄下,本文給大家詳細講解,需要的朋友可以參考下
    2023-05-05
  • Vue2.0+Vux搭建一個完整的移動webApp項目的示例

    Vue2.0+Vux搭建一個完整的移動webApp項目的示例

    這篇文章主要介紹了Vue2.0+Vux搭建一個完整的移動webApp項目的示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-03-03
  • Vue面試題及Vue知識點整理

    Vue面試題及Vue知識點整理

    這篇文章主要介紹了Vue面試題及Vue知識點整理,本文給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友參考下吧
    2018-10-10
  • vue子路由跳轉實現(xiàn)tab選項卡效果

    vue子路由跳轉實現(xiàn)tab選項卡效果

    這篇文章主要為大家詳細介紹了vue子路由跳轉實現(xiàn)tab選項卡效果,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • vue如何使用文件流進行下載(new Blob)

    vue如何使用文件流進行下載(new Blob)

    這篇文章主要介紹了vue如何使用文件流進行下載(new Blob),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-09-09
  • vue如何使用js對圖片進行點擊標注圓點并記錄它的坐標

    vue如何使用js對圖片進行點擊標注圓點并記錄它的坐標

    這篇文章主要介紹了vue如何使用js對圖片進行點擊標注圓點并記錄它的坐標,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-04-04
  • 手寫Vue內置組件component的實現(xiàn)示例

    手寫Vue內置組件component的實現(xiàn)示例

    本文主要介紹了手寫Vue內置組件component的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-07-07
  • Vue3封裝全局函數式組件方法總結

    Vue3封裝全局函數式組件方法總結

    函數式組件就是沒有管理任何狀態(tài),也沒有監(jiān)聽任何傳遞給它的狀態(tài),也沒有生命周期方法,它只是一個接受一些 prop 的函數,下面這篇文章主要給大家介紹了關于Vue3封裝全局函數式組件方法的相關資料,需要的朋友可以參考下
    2023-06-06

最新評論