<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
eventBus是在vue中經常用來解決跨元件訊息傳遞的問題,但對它的使用要特別注意,否則會產生很嚴重的後果。
本文介紹了eventBus的實現原理,並介紹它如何在vue中使用,並舉了一個具體的例子來說明,如果使用不當,它會造成記憶體漏失。
要注意eventBus並不是前端的概念。
由greenrobot [1] 組織貢獻(該組織還貢獻了greenDAO),一個Android事件釋出/訂閱輕量級框架,
功能:通過解耦釋出者和訂閱者簡化Android事件傳遞 [2]
EventBus可以代替Android傳統的Intent,Handler,Broadcast或介面函數,在Fragment,Activity,Service執行緒之間傳遞資料,執行方法。
特點:程式碼簡潔,是一種釋出訂閱設計模式(觀察者設計模式)。
eventBus是事件匯流排的意思,它本質上是一個釋出訂閱者實現,在vue2.X中,vue範例上提供了$on,$emit,$off這三個方法,分別用來新增觀察者,釋出事件,取消訂閱這三個操作。
所以,我們可以直接把一個vue範例掛到Vue的原型上來充當元件相互通訊的中介。
Vue.prototype.$eventBus = new Vue()
這樣一來,所有的Vue元件都可以沿著原型鏈找到這個$eventBus,從而存取$on, $off,$emit。
它可以幫助我們實現跨元件的通訊。
在根元件中釋出事件,在兩個子元件中去監聽事件。
<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>
在建立com1元件時,訂閱event1事件;在建立com2元件時,訂閱event2事件;在建立根元件(vue範例)時,開啟定時器:每隔3s釋出事件,這樣的話,com1和com2就都可以收到事件,並執行對應的回撥。
效果如下:
如果不及時取消訂閱,則回撥函數仍會執行,更嚴重的是,如果在事件處理回撥函數中參照了外部變數形成了閉包,則會導致記憶體漏失。
下面的程式碼說明這個問題。
在根元件(vue範例)中,補充一個資料項showCom1,並設定v-if指令來實現銷燬和重建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('建立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事件還能再收到嗎?對應的回撥函數還能再執行嗎?一般的想法是元件都銷燬了,那它訂閱的事件肯定也收不到了嘛
。
答案是:還能收到。原因很簡單:事件訂閱這功能是$eventBus物件完成的,與這個com1元件無關。
上面的程式碼執行的效果,是這樣的:
下面再來說明記憶體漏失的問題,把com1的元件內容改成如下:
Vue.component('com1', { template:`<div>com1</div>`, created () { console.log('建立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”,再次新增一個快照,你會發現這個空間並沒有釋放掉。
解釋如下:
上面是這個過程的示意圖,由於沒有及時取消訂閱f1,所以arr這個陣列並沒有釋放掉。
解決方案:
在com1的destoryed勾點中,呼叫$off來取消訂閱。
destroyed () { // 取消所有對event1事件的監聽 this.$eventBus.$off('event1') }
偵錯結果如下:
可見,com1刪除之後,這個數值的空間釋放掉了,同時它的事件監聽函數也不會再執行了。
$off的格式:
父子元件的created和mounted的區別, 按執行順序:
所以,到底在哪個勾點中訂閱,在哪個勾點中釋出,要根據情況來定。
eventBus是一個名詞,並非前端獨有;
new Vue() 得到的範例上已經實現了釋出訂閱模式,可以直接做eventBus使用;
使用eventBus要及時呼叫$off;
本篇文章就到這裡了,希望能夠給你帶來幫助,也希望您能夠多多關注it145.com的更多內容!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45