前端的狀態(tài)管理(上)
前言:
提到狀態(tài)管理大家可能馬上就想到:Vuex、Redux、Flux、Mobx等等方案。其實(shí)不然,不論哪種方案只要內(nèi)容一多起來(lái)似乎都是令人頭疼的問(wèn)題,也許你有適合自己的解決方案又或者簡(jiǎn)單的注釋和區(qū)分模塊,今天來(lái)聊一聊前端的狀態(tài)管理,如果你有好的建議或問(wèn)題歡迎在下方留言提出。
1、什么是前端狀態(tài)管理?
舉個(gè)例子:圖書(shū)館里所有人都可以隨意進(jìn)書(shū)庫(kù)借書(shū)還書(shū),如果人數(shù)不多,這種方式可以提高效率減少流程,一旦人數(shù)多起來(lái)就容易混亂,書(shū)的走向不明確,甚至丟失。所以需要一個(gè)圖書(shū)管理員來(lái)專(zhuān)門(mén)記錄借書(shū)的記錄,也就是你要委托圖書(shū)管理員給你借書(shū)及還書(shū)。
實(shí)際上,大多數(shù)狀態(tài)管理方案都是如上思想,通過(guò)管理員(比如 Vuex)去規(guī)范書(shū)庫(kù)里書(shū)本的借還(項(xiàng)目中需要存儲(chǔ)的數(shù)據(jù))
2、Vuex
在國(guó)內(nèi)業(yè)務(wù)使用中 Vuex 的比例應(yīng)該是最高的,Vuex 也是基于 Flux 思想的產(chǎn)品,Vuex 中的 state 是可以被修改的。原因和 Vue 的運(yùn)行機(jī)制有關(guān)系,Vue 基于 ES5 中的 getter/setter 來(lái)實(shí)現(xiàn)視圖和數(shù)據(jù)的雙向綁定,因此 Vuex 中 state 的變更可以通過(guò) setter 通知到視圖中對(duì)應(yīng)的指令來(lái)實(shí)現(xiàn)視圖更新。更改 Vuex 的 store 中的狀態(tài)的唯一方法是提交 mutation。我們以圖書(shū)館來(lái)作為例子:
const state = {
book: 0
}
const mutations = {
borrow_book(state) {
state.book ++
}
}
//調(diào)用時(shí)
store.commit('borrow_book')
那還有action呢? 在 mutation 中混合異步調(diào)用會(huì)導(dǎo)致你的程序很難調(diào)試。你怎么知道是哪個(gè)先執(zhí)行完呢? aciton 可以包含任意異步操作,用法跟上面基本類(lèi)似,不再敘述。
其實(shí)我只是拿 Vuex 來(lái)淺入一下相關(guān)用法大家應(yīng)該是都熟悉了,那 Vuex 解決了什么問(wèn)題呢?
- 管理多個(gè)組件共享狀態(tài)。
- 全局狀態(tài)管理。
- 狀態(tài)變更跟蹤。
- 讓狀態(tài)管理形成一種規(guī)范,使代碼結(jié)構(gòu)更清晰。
實(shí)際上大部分程序員都比較懶(狗頭保命),只是為了能多個(gè)組件共享狀態(tài),至于其他的都是事后了。最典型的就是加入購(gòu)物車(chē)的數(shù)量,加入一個(gè)就通過(guò) Vuex 記錄保存最終的總數(shù)顯示在下欄。
那問(wèn)題來(lái)了,既然你的目的只是共享多個(gè)狀態(tài),那何不直接用 Bus 總線好了?
3、Bus 總線
Bus 總線實(shí)際上他是一個(gè)公共的 Vue 實(shí)例,專(zhuān)門(mén)處理 emit 和 on 事件。
實(shí)際上 Bus 總線十分輕便,他并不存在 Dom 結(jié)構(gòu),他僅僅只是具有實(shí)例方法而已。
Vue.prototype.$Bus = new Vue()
然后,你可以通過(guò) emit 來(lái)發(fā)送事件, on 來(lái)接收事件。
// 發(fā)送事件
this.$Bus.$emit('borrow_book', 1)
// 任意組件中接收
this.$Bus.$on('borrow_book', (book) => {
console.log(`借了${book}本書(shū)`)
})
當(dāng)然還有 off(移除)、once(監(jiān)聽(tīng)一次)等操作感興趣可以自行搜索引擎。
怎么樣?上面對(duì)于滿足共享一個(gè)狀態(tài)是不是比 Vuex 要簡(jiǎn)單多了?實(shí)際上確實(shí)是簡(jiǎn)單多了,但這也代表他比較適合中小型項(xiàng)目。多于大型項(xiàng)目來(lái)說(shuō) Bus 只會(huì)讓你追述更改源時(shí)一臉懵逼甚至你都不知道他在哪里改變了。
他的工作原理就是發(fā)布訂閱者的思想,雖然非常優(yōu)雅簡(jiǎn)單,但實(shí)際 Vue 并不提倡這種寫(xiě)法,并在3.0版本中移除了大部分相關(guān)Api(emit、on等),其實(shí)不然,發(fā)布訂閱模式我們可以自己手寫(xiě)一個(gè)去實(shí)現(xiàn):
class Bus {
constructor() {
// 收集訂閱信息,調(diào)度中心
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;
簡(jiǎn)單吧?你只需要跟用 Vue Bus 一樣去實(shí)例化然后用就可以了。什么?你想共享兩三個(gè)甚至更少的狀態(tài)(一個(gè)),那封裝一個(gè) Bus 是不是有點(diǎn)沒(méi)必要了? 行吧,那你用 web storage 吧。
4、web storage
其實(shí)說(shuō)到這,storage只是數(shù)據(jù)存儲(chǔ)方式,跟狀態(tài)管理其實(shí)沒(méi)有太大關(guān)系,只是共享數(shù)據(jù)。但是既然都提到了那就順帶說(shuō)一下(狗頭)
web storage 有這三種:cookie、local storage、session storage。
無(wú)論這三種的哪種都強(qiáng)烈建議不要將敏感信息放入其中,這里應(yīng)該是加密或一些不那么重要的數(shù)據(jù)在里面。
先簡(jiǎn)單復(fù)習(xí)一下三者:

cookie 不必多說(shuō),大家發(fā)起請(qǐng)求時(shí)經(jīng)常會(huì)攜帶cokie請(qǐng)求一些個(gè)人數(shù)據(jù)等,與我們要探討的內(nèi)容沒(méi)有太大關(guān)系。loaclStorage 可以存儲(chǔ)理論上永久有效的數(shù)據(jù),如果你要存儲(chǔ)狀態(tài)一般推薦是放在 sessionStorage,localStorage 也有以下局限:
- 瀏覽器的大小不統(tǒng)一,并且在 IE8 以上的 IE 版本才支持
localStorage這個(gè)屬性。 - 目前所有的瀏覽器中都會(huì)把
localStorage的值類(lèi)型限定為string類(lèi)型,這個(gè)在對(duì)我們?nèi)粘1容^常見(jiàn)的JSON對(duì)象類(lèi)型需要一些轉(zhuǎn)換。 localStorage在瀏覽器的隱私模式下面是不可讀取的。localStorage本質(zhì)上是對(duì)字符串的讀取,如果存儲(chǔ)內(nèi)容多的話會(huì)消耗內(nèi)存空間,會(huì)導(dǎo)致頁(yè)面變卡。localStorage不能被爬蟲(chóng)抓取到。
localStorage 與 sessionStorage 的唯一一點(diǎn)區(qū)別就是 localStorage 屬于永久性存儲(chǔ),而 sessionStorage 屬于當(dāng)會(huì)話結(jié)束的時(shí)候,sessionStorage 中的鍵值對(duì)會(huì)被清空。
localStorage 本身只支持字符串形式存儲(chǔ),所以你存整數(shù)類(lèi)型,拿出來(lái)的會(huì)是字符串類(lèi)型。
sessionStorage 與 localStorage 基本差不多,只是回話關(guān)閉時(shí),數(shù)據(jù)就會(huì)清空。
總結(jié):
不論哪種方案選擇合適自己項(xiàng)目的方案才是最佳實(shí)踐。沒(méi)有最好的方案,只有合適自己的方案。
到此這篇關(guān)于前端的狀態(tài)管理的文章就介紹到這了,更多相關(guān)前端的狀態(tài)管理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
微信小程序 設(shè)置啟動(dòng)頁(yè)面的兩種方法
這篇文章主要介紹了 微信小程序 設(shè)置啟動(dòng)頁(yè)面的方法的相關(guān)資料,這里對(duì)設(shè)置啟動(dòng)頁(yè)面的兩種方法分別介紹,需要的朋友可以參考下2017-03-03
輸入框跟隨文字內(nèi)容適配寬實(shí)現(xiàn)示例
這篇文章主要為大家介紹了輸入框跟隨文字內(nèi)容適配寬實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08
微信小程序 支付功能實(shí)現(xiàn)PHP實(shí)例詳解
這篇文章主要介紹了微信小程序 支付功能實(shí)現(xiàn)PHP實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下2017-05-05
JavaScript獲取上傳文件相關(guān)信息示例詳解
這篇文章主要為大家介紹了JavaScript獲取上傳文件相關(guān)信息示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08
微信小程序 tabs選項(xiàng)卡效果的實(shí)現(xiàn)
這篇文章主要介紹了微信小程序 tabs選項(xiàng)卡效果的實(shí)現(xiàn)的相關(guān)資料,微信小程序內(nèi)部組件沒(méi)有Tabs 選項(xiàng)卡的功能,自己實(shí)現(xiàn)個(gè)類(lèi)似的,需要的朋友可以參考下2017-01-01
微信小程序 頁(yè)面跳轉(zhuǎn)和數(shù)據(jù)傳遞實(shí)例詳解
這篇文章主要介紹了微信小程序 頁(yè)面跳轉(zhuǎn)和數(shù)據(jù)傳遞實(shí)例詳解的相關(guān)資料,這里附有實(shí)例代碼幫助到家學(xué)習(xí)理解,需要的朋友可以參考下2017-01-01

