前端的狀態(tài)管理(上)
前言:
提到狀態(tài)管理大家可能馬上就想到:Vuex
、Redux
、Flux
、Mobx
等等方案。其實不然,不論哪種方案只要內容一多起來似乎都是令人頭疼的問題,也許你有適合自己的解決方案又或者簡單的注釋和區(qū)分模塊,今天來聊一聊前端的狀態(tài)管理,如果你有好的建議或問題歡迎在下方留言提出。
1、什么是前端狀態(tài)管理?
舉個例子:圖書館里所有人都可以隨意進書庫借書還書,如果人數(shù)不多,這種方式可以提高效率減少流程,一旦人數(shù)多起來就容易混亂,書的走向不明確,甚至丟失。所以需要一個圖書管理員來專門記錄借書的記錄,也就是你要委托圖書管理員給你借書及還書。
實際上,大多數(shù)狀態(tài)管理方案都是如上思想,通過管理員(比如 Vuex)去規(guī)范書庫里書本的借還(項目中需要存儲的數(shù)據(jù))
2、Vuex
在國內業(yè)務使用中 Vuex
的比例應該是最高的,Vuex
也是基于 Flux
思想的產(chǎn)品,Vuex
中的 state
是可以被修改的。原因和 Vue 的運行機制有關系,Vue
基于 ES5
中的 getter/setter
來實現(xiàn)視圖和數(shù)據(jù)的雙向綁定,因此 Vuex
中 state
的變更可以通過 setter
通知到視圖中對應的指令來實現(xiàn)視圖更新。更改 Vuex
的 store
中的狀態(tài)的唯一方法是提交 mutation
。我們以圖書館來作為例子:
const state = { book: 0 } const mutations = { borrow_book(state) { state.book ++ } } //調用時 store.commit('borrow_book')
那還有action
呢? 在 mutation
中混合異步調用會導致你的程序很難調試。你怎么知道是哪個先執(zhí)行完呢? aciton
可以包含任意異步操作,用法跟上面基本類似,不再敘述。
其實我只是拿 Vuex 來淺入一下相關用法大家應該是都熟悉了,那 Vuex 解決了什么問題呢?
- 管理多個組件共享狀態(tài)。
- 全局狀態(tài)管理。
- 狀態(tài)變更跟蹤。
- 讓狀態(tài)管理形成一種規(guī)范,使代碼結構更清晰。
實際上大部分程序員都比較懶(狗頭保命),只是為了能多個組件共享狀態(tài),至于其他的都是事后了。最典型的就是加入購物車的數(shù)量,加入一個就通過 Vuex 記錄保存最終的總數(shù)顯示在下欄。
那問題來了,既然你的目的只是共享多個狀態(tài),那何不直接用 Bus
總線好了?
3、Bus 總線
Bus
總線實際上他是一個公共的 Vue 實例,專門處理 emit
和 on
事件。
實際上 Bus 總線十分輕便,他并不存在 Dom
結構,他僅僅只是具有實例方法而已。
Vue.prototype.$Bus = new Vue()
然后,你可以通過 emit
來發(fā)送事件, on
來接收事件。
// 發(fā)送事件 this.$Bus.$emit('borrow_book', 1) // 任意組件中接收 this.$Bus.$on('borrow_book', (book) => { console.log(`借了${book}本書`) })
當然還有 off
(移除)、once
(監(jiān)聽一次)等操作感興趣可以自行搜索引擎。
怎么樣?上面對于滿足共享一個狀態(tài)是不是比 Vuex 要簡單多了?實際上確實是簡單多了,但這也代表他比較適合中小型項目。多于大型項目來說 Bus
只會讓你追述更改源時一臉懵逼甚至你都不知道他在哪里改變了。
他的工作原理就是發(fā)布訂閱者的思想,雖然非常優(yōu)雅簡單,但實際 Vue
并不提倡這種寫法,并在3.0版本中移除了大部分相關Api
(emit、on等),其實不然,發(fā)布訂閱模式我們可以自己手寫一個去實現(xiàn):
class Bus { constructor() { // 收集訂閱信息,調度中心 this.list = {}; } // 訂閱 $on(name, fn) { this.list[name] = this.list[name] || []; this.list[name].push(fn); } // 發(fā)布 $emit(name, data) { if (this.list[name]) { this.list[name].forEach((fn) => { fn(data); }); } } // 取消訂閱 $off(name) { if (this.list[name]) { delete this.list[name]; } } } export default Bus;
簡單吧?你只需要跟用 Vue Bus
一樣去實例化然后用就可以了。什么?你想共享兩三個甚至更少的狀態(tài)(一個),那封裝一個 Bus
是不是有點沒必要了? 行吧,那你用 web storage
吧。
4、web storage
其實說到這,storage
只是數(shù)據(jù)存儲方式,跟狀態(tài)管理其實沒有太大關系,只是共享數(shù)據(jù)。但是既然都提到了那就順帶說一下(狗頭)
web storage
有這三種:cookie
、local storage
、session storage
。
無論這三種的哪種都強烈建議不要將敏感信息放入其中,這里應該是加密或一些不那么重要的數(shù)據(jù)在里面。
先簡單復習一下三者:
cookie
不必多說,大家發(fā)起請求時經(jīng)常會攜帶cokie
請求一些個人數(shù)據(jù)等,與我們要探討的內容沒有太大關系。loaclStorage
可以存儲理論上永久有效的數(shù)據(jù),如果你要存儲狀態(tài)一般推薦是放在 sessionStorage
,localStorage
也有以下局限:
- 瀏覽器的大小不統(tǒng)一,并且在 IE8 以上的 IE 版本才支持
localStorage
這個屬性。 - 目前所有的瀏覽器中都會把
localStorage
的值類型限定為string
類型,這個在對我們日常比較常見的JSON
對象類型需要一些轉換。 localStorage
在瀏覽器的隱私模式下面是不可讀取的。localStorage
本質上是對字符串的讀取,如果存儲內容多的話會消耗內存空間,會導致頁面變卡。localStorage
不能被爬蟲抓取到。
localStorage
與 sessionStorage
的唯一一點區(qū)別就是 localStorage
屬于永久性存儲,而 sessionStorage
屬于當會話結束的時候,sessionStorage
中的鍵值對會被清空。
localStorage
本身只支持字符串形式存儲,所以你存整數(shù)類型,拿出來的會是字符串類型。
sessionStorage
與 localStorage
基本差不多,只是回話關閉時,數(shù)據(jù)就會清空。
總結:
不論哪種方案選擇合適自己項目的方案才是最佳實踐。沒有最好的方案,只有合適自己的方案。
到此這篇關于前端的狀態(tài)管理的文章就介紹到這了,更多相關前端的狀態(tài)管理內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
詳解微信小程序 通過控制CSS實現(xiàn)view隱藏與顯示
這篇文章主要介紹了微信小程序 通過控制CSS實現(xiàn)view隱藏與顯示的相關資料,需要的朋友可以參考下2017-05-05TypeScript新語法之infer?extends示例詳解
這篇文章主要為大家介紹了TypeScript新語法之infer?extends示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-08-085種 JavaScript 方式實現(xiàn)數(shù)組扁平化
這篇文章主要介紹5種 JavaScript 方式實現(xiàn)數(shù)組扁平化,雖說只有5種方法,但是核心只有一個就是遍歷數(shù)組arr,若arr[i]為數(shù)組則遞歸遍歷,直至arr[i]不為數(shù)組然后與之前的結果concat。 想具體了解的小伙伴那請看下面文章內容吧2021-09-09