vue使用pinia實現(xiàn)全局無縫通信
前言
細數(shù) vue 中的數(shù)據(jù)通信方式,足足有十幾種,其中包括了父子互傳、兄弟互傳、隔代互傳、無關(guān)互傳,這十幾種方式每個都有其不同的語法,也就是說我們需要根據(jù)這些組件的親戚關(guān)系選擇最合適的通信方式,我們無時無刻不在使用各種形式的參數(shù)傳遞。MD,像極了我們混亂的前端框架圈。
mqtt 協(xié)議
MQTT(Message Queuing Telemetry Transport,消息隊列遙測傳輸協(xié)議),是一種基于發(fā)布/訂閱
(publish/subscribe
)模式的“輕量級”通訊協(xié)議,該協(xié)議構(gòu)建于TCP/IP協(xié)議上,由IBM在1999年發(fā)布,適用于 低性能 的物聯(lián)網(wǎng)設(shè)備。
為什么要提mqtt呢,因為我接下來要說的和mqtt的通信方式息息相關(guān)。
首先簡單介紹下 mqtt 這個東西,簡單來說,它由三個部分組成:服務(wù)器(mqtt broker)、發(fā)布者(publisher)、訂閱者(subscriber)。其中發(fā)布者和訂閱者的身份通常是混合的,即一個用戶可以既是發(fā)布者又是訂閱者,當發(fā)布消息時,就是發(fā)布者,當訂閱時,就是訂閱者。
在發(fā)布消息時,需要指定一個主題(topic),當然,訂閱時也要指定一個主題。向某個主題發(fā)布消息時,服務(wù)器會向所有訂閱這個主題的客戶端分發(fā)消息,當訂閱者接收到時,再根據(jù)消息內(nèi)容進行它的下一步操作。
舉個例子,大概是:你(訂閱者)跟你媽(服務(wù)器)說,你弟弟(發(fā)布者)打游戲就告訴你,你好打他,然后你媽說好的(訂閱成功),然后你弟弟打游戲(發(fā)布)的一瞬間,消息被你媽捕獲到了,然后告你了,你就成功打了你弟弟。
在上面的例子中,你通過訂閱消息,而后執(zhí)行了某些操作
發(fā)布訂閱思想
我們都知道,vue的雙向綁定原理是基于發(fā)布訂閱范式的(面試必備,擦,哥們)。想必你和我一樣,即使看了幾遍 vue 雙向綁定原理,還是對這個字眼不太理解,什么叫發(fā)布訂閱范式,發(fā)布訂閱在生活和編程中無處不在,是一種通俗意義,并不是編程專有術(shù)語。
其實,vue 中的 watch / watchEffect 就是一個訂閱的表現(xiàn)。
watch(someValue,()=>{ // ... })
上面的代碼,訂閱了 someValue
的值變化這一事件
。但是好像這個例子中缺失了發(fā)布者,其實發(fā)布者是隱式存在的。
someValue = otherValue
此時,這個js 語句
就成了 發(fā)布者。
vue3 中的 watch 方法十分強大,它支持 深度監(jiān)聽、監(jiān)聽對象、對象下的單個屬性、多變量監(jiān)聽等。
使用 watch 和 pinia 實現(xiàn)全局事件發(fā)布訂閱
通過上面的描述,不難發(fā)現(xiàn)用 watch 來監(jiān)聽 pinia 中的某些屬性,即可達到訂閱的效果,從而實現(xiàn)無障礙 傳參/通信,那么我們把所有涉及傳參和通信的場景都使用 pinia ,可行嗎?
我認為可行,以這種方式傳參,完全不用考慮值從哪里來,將要到哪里去。哪里用,就在哪里 watch。
適用場景
通過監(jiān)聽全局變量變化從而執(zhí)行下一步操作的這種寫法,聽起來好像對性能影響很大,而實際上呢,pinia 對此已經(jīng)做了比較合適的機制,首先 Pinia store 依靠 pinia
實例在所有調(diào)用中共享同一個 store 實例,你可以定義任意多的 store,而這些 store 不會單獨占用內(nèi)存,所以放心大膽的在多文件中創(chuàng)建 store 即可。
比如,現(xiàn)在有一個 全局的地圖組件mapbox
,又有若干個小組件控制著地圖上的圖層的增刪改查,我們無需在每個組件中都向mapbox
組件傳值、或者用ref
獲取其實例,我們只需把需要的數(shù)據(jù)放到pinia中,然后在mapbox
組件內(nèi)對其監(jiān)聽。
// Mapbox.vue watch(() => store.currGridData, (newValue) => { renderGrid(newValue) })
上面的代碼中監(jiān)聽了store.currGridData
數(shù)據(jù),當其數(shù)據(jù)有變化時,則重新渲染此數(shù)據(jù)。當然,如果需要清除,就直接把此數(shù)據(jù)置空就好了,可以在監(jiān)聽中新增空數(shù)據(jù)處理,或者在renderGrid
函數(shù)中處理。
這么一來,所有的組件,無論在什么位置,什么路徑,只要監(jiān)聽某值的變化,即可做到類似傳值的效果。
潛在的問題
內(nèi)存泄露
當然世界上沒有十全十美的事情,這么干正常情況下對性能幾乎是沒有影響的,但一旦出現(xiàn)問題,那將是致命的。雖然 pinia 的實例是單例的,但是引用卻不是,每新增一個 對store值的watch,就會新增一個對此值的引用,正常情況下,vue會主動在頁面銷毀時移除這些 watch,但是如果 watch 放在了異步體內(nèi),則需要注意手動移除它們,否則就會使這些內(nèi)存常駐,也就是內(nèi)存泄露。
死循環(huán)
完全依靠 watch 來執(zhí)行操作,會在不經(jīng)意間造成死循環(huán)或者棧溢出的問題。舉個例子
watch(()=>store.someValue,()=>{ store.someValue = otherValue })
如果otherValue的值是一個固定值,那么在下一次將不再進入了,因為值沒有再變化,但是如果值不是固定值,很容易看出來,這個 watch 實際上是一個死循環(huán),當操作了store.someValue
的值后,又會重新回到這個watch。要避免這個問題也很簡單,像通常的遞歸函數(shù)一樣,給他一個跳出的條件即可
watch(()=>store.someValue,(nv)=>{ if(nv == someValue) return store.someValue = otherValue })
不觸發(fā)問題
當監(jiān)聽的某值不變化時,watch 不會觸發(fā),這樣就會導(dǎo)致另一個問題,如果依賴某個值的變化來做一些操作,而這個操作和這個值的變化又不是雙向耦合的,此時就會造成給某值賦值時,不會觸發(fā) watch。
例如通過值goNewArea
來使地圖跳轉(zhuǎn)到新的地區(qū)視角。
watch(()=>store.goNewArea,()=>{ map.flyTo({ // ... }) })
比如有一個按鈕,會將其賦值為北京市
,那么地圖正常跳轉(zhuǎn)到北京,如果此時我們通過拉動地圖視角,使實際區(qū)域變成了上海市
,此時再通過按鈕將其賦值為北京市
時,地圖將不會觸發(fā)跳轉(zhuǎn),因為store.goNewArea
沒有變化。
要解決這個問題,則應(yīng)該給這個值一個置空。即:
watch(()=>store.goNewArea,()=>{ map.flyTo({ // ... }) map.once('moveend',()=>{ store.goNewArea = "" }) })
上面提到,這樣做會導(dǎo)致watch重復(fù)觸發(fā)死循環(huán)的問題,所以還要再加一句:
watch(()=>store.goNewArea,(nv)=>{ if(nv == "") return map.flyTo({ // ... }) map.once('moveend',()=>{ store.goNewArea = "" }) })
總結(jié)
使用 watch 配合 pinia 全局變量,來實現(xiàn)全局的事件控制,在一定意義上簡化了開發(fā)流程,說實話,寫起來非常爽,也非常清晰。但是一旦變量多起來,相互影響的概論就會增大,管理龐大的 watch 們也是一項負擔(dān),你需要時刻注意不要內(nèi)存溢出、死循環(huán)。
總之這種寫法的靈活性拉滿了,但是需要非常清晰的思路和對業(yè)務(wù)深刻的理解,才能游刃有余。
到此這篇關(guān)于vue使用pinia實現(xiàn)全局無縫通信的文章就介紹到這了,更多相關(guān)vue pinia全局無縫通信內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
import.meta.glob() 如何導(dǎo)入多個目錄下的資源(最新推薦)
import.meta.glob() 其實不僅能接收一個字符串,還可以接收一個字符串數(shù)組,就是匹配多個位置,本文給大家介紹import.meta.glob() 如何導(dǎo)入多個目錄下的資源,感興趣的朋友一起看看吧2023-11-11vue3實現(xiàn)無縫滾動列表效果(大屏數(shù)據(jù)輪播場景)
vue3-scroll-seamless 是一個用于 Vue 3 的插件,用于實現(xiàn)無縫滾動的組件,它可以讓內(nèi)容在水平或垂直方向上無縫滾動,適用于展示輪播圖、新聞滾動、圖片展示等場景,本文就給大家介紹了vue3實現(xiàn)無縫滾動列表效果,需要的朋友可以參考下2024-07-07vue中調(diào)用百度地圖獲取經(jīng)緯度的實現(xiàn)
最近做個項目,需要實現(xiàn)獲取當前位置的經(jīng)緯度,所以本文主要介紹了vue中調(diào)用百度地圖獲取經(jīng)緯度的實現(xiàn),文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-08-08