摘要:是一個(gè)的簡(jiǎn)單可擴(kuò)展的狀態(tài)管理庫(kù)。它的副作用是自動(dòng)更新。該函數(shù)返回一個(gè)值,當(dāng)返回值為的時(shí)候,才會(huì)繼續(xù)觸發(fā)第一個(gè)函數(shù)。當(dāng)返回值為時(shí),不再繼續(xù)監(jiān)聽(tīng)。包含一個(gè),該值用來(lái)區(qū)分執(zhí)行事件的類(lèi)型。
mobx 能干什么
使用 react 寫(xiě)小型應(yīng)用,數(shù)據(jù)、業(yè)務(wù)邏輯和視圖的模塊劃分不是很細(xì)是沒(méi)有問(wèn)題的。在這個(gè)階段,引入任何狀態(tài)管理庫(kù),都算是奢侈的。但是隨著頁(yè)面邏輯的復(fù)雜度提升,在中大型應(yīng)用中,數(shù)據(jù)、業(yè)務(wù)邏輯和視圖,如果不能很好的劃分,就很有可能出現(xiàn)維護(hù)難、性能低下的問(wèn)題。
業(yè)內(nèi)比較成熟的解決方案有 redux,但是 redux 使用過(guò)程中,給我的感覺(jué)是太復(fù)雜和繁瑣。那么為什么不簡(jiǎn)單一點(diǎn)呢?mobx 的核心理念是 簡(jiǎn)單、可擴(kuò)展的狀態(tài)管理庫(kù)。這可能正是你想要的。
react 關(guān)注的狀態(tài)(state)到視圖(view)的問(wèn)題。而 mobx 關(guān)注的是狀態(tài)倉(cāng)庫(kù)(store)到的狀態(tài)(state)的問(wèn)題。
核心的概念1mobx 最最核心的概念只有2個(gè)。 @observable 和 @observer ,它們分別對(duì)應(yīng)的是被觀察者和觀察者。這是大家常見(jiàn)的觀察者模式,不過(guò)這里使用了,ES7 中的 裝飾器。
使用 @observable 可以觀察類(lèi)的值。
這里使用 @observable 將 Store 的 todos 變?yōu)橐粋€(gè)被觀察的值。
observable倉(cāng)庫(kù)
// 這里引入的是 mobx import {observable} from "mobx"; class Store { @observable todos = [{ title: "todo標(biāo)題", done: false, }]; }observer
mobx 組件
然后再使用 @observer ,將組件變?yōu)橛^察者,響應(yīng) todos 狀態(tài)變化。
當(dāng)狀態(tài)變化時(shí),組件也會(huì)做相應(yīng)的更新。
// 這里引入的是 mobx-react import {observer} from "mobx-react"; @observer class TodoBox extends Component { render() { return (
完整的 demo 如下。
import React, {Component} from "react"; import { render } from "react-dom"; import {observable} from "mobx"; import {observer} from "mobx-react"; // 最簡(jiǎn)單的 mobx 就是一個(gè)觀察者模式 class Store { // 被觀察者 @observable todos = [{ title: "完成 Mobx 翻譯", done: false, }]; } // 觀察者 @observer class TodoBox extends Component { render() { return (
通過(guò)以上的簡(jiǎn)單的例子,展現(xiàn)了 mobx 分離數(shù)據(jù)、視圖的能力。
核心概念2這一小節(jié)要介紹的兩個(gè)概念雖然也是核心概念,但是是可選的。
前面例子,只講了狀態(tài)的讀取,那么狀態(tài)應(yīng)該如何寫(xiě)入呢?
答案是直接寫(xiě)入!
@observer class TodoBox extends Component { render() { return () } }{this.props.store.todos.map( (todo,index) =>
- {todo.title}
)}{ // 直接修改倉(cāng)庫(kù)中的狀態(tài)值 this.props.store.todos[0].title = "修改后的todo標(biāo)題" }} value="點(diǎn)我"/>
細(xì)心的朋友一定發(fā)現(xiàn)了奇怪的地方,react 官方說(shuō)過(guò) props 值不能直接修改,但是引入 mobx 后 props 可以直接修改了,這太奇怪了!
解決辦法就是 mobx 的下一個(gè)概念 action。
actions首先在 Store 中,定義一個(gè) action。
class Store { @observable todos = [{ title: "todo標(biāo)題", done: false, }]; @action changeTodoTitle({index,title}){ this.todos[index].title = title } }
在 Component 中調(diào)用,這樣通過(guò) action 的方法,就避免了直接修改 props 的問(wèn)題。
{ this.props.store.changeTodoTitle({index:0,title:"修改后的todo標(biāo)題"}); }} value="點(diǎn)我"/>
可以通過(guò)引入 mobx 定義的嚴(yán)格模式,強(qiáng)制使用 action 來(lái)修改狀態(tài)。
import {useStrict} from "mobx"; useStrict(true);computed values
在有些時(shí)候,state 并不一定是我們需要的最終數(shù)據(jù)。例如,所有的 todo 都放在 store.todos 中,而已經(jīng)完成的 todos 的值(store.unfinishedTodos),可以由 store.todos 衍生而來(lái)。
對(duì)此,mobx 提供了 computed 裝飾器,用于獲取由基礎(chǔ) state 衍生出來(lái)的值。如果基礎(chǔ)值沒(méi)有變,獲取衍生值時(shí)就會(huì)走緩存,這樣就不會(huì)引起虛擬 DOM 的重新渲染。
通過(guò) @computed + getter 函數(shù)來(lái)定義衍生值(computed values)。
import { computed } from "mobx"; class Store { @observable todos = [{ title: "todo標(biāo)題", done: false, },{ title: "已經(jīng)完成 todo 的標(biāo)題", done: true, }]; @action changeTodoTitle({index,title}){ this.todos[index].title = title } @computed get finishedTodos () { return this.todos.filter((todo) => todo.done) } }
mobx 有一套機(jī)制,如果衍生值(computed values)所依賴的基礎(chǔ)狀態(tài)(state)沒(méi)有發(fā)生改變,獲取衍生值時(shí),不會(huì)重新計(jì)算,而是走的緩存。因此 mobx 不會(huì)引起過(guò)度渲染,從而保障了性能。
當(dāng)渲染的值為 finishedTodos ,點(diǎn)擊修改標(biāo)題,不會(huì)在控制臺(tái)打印 "render";
換成 todos,就會(huì)打印 "render".
這是由于已完成的 todos 值沒(méi)有改變,所以不會(huì)重新計(jì)算,而是走的緩存。因此不會(huì)調(diào)用 render 方法。
完整 demo 如下
import React, {Component} from "react"; import { render } from "react-dom"; import {observable, action, computed,useStrict} from "mobx"; import {observer} from "mobx-react"; useStrict(true); class Store { @observable todos = [{ title: "todo標(biāo)題", done: false, },{ title: "已經(jīng)完成 todo 的標(biāo)題", done: true, }]; @action changeTodoTitle({index,title}){ this.todos[index].title = title } @computed get unfinishedTodos () { return this.todos.filter((todo) => todo.done) } } @observer class TodoBox extends Component { render() { console.log("render"); return (小結(jié)) } } const store = new Store(); render({ /* 把 unfinishedTodos 換成 todos,點(diǎn)擊修改標(biāo)題就會(huì)在控制臺(tái)打印 "render".*/ } {this.props.store.unfinishedTodos.map( (todo,index) =>
- {todo.title}
)}{ this.props.store.changeTodoTitle({index:0,title:"修改后的todo標(biāo)題"}); }} value="修改標(biāo)題"/>, document.getElementById("root") );
翻譯了官網(wǎng)的一段文章,就拿過(guò)來(lái)做小結(jié)了。
mobx 是一個(gè)的簡(jiǎn)單、可擴(kuò)展的狀態(tài)管理庫(kù)。它背后的哲學(xué)非常簡(jiǎn)單:
應(yīng)用程序 state 是最基礎(chǔ)的數(shù)據(jù)。任何可以從 state 中衍生出來(lái)的數(shù)據(jù),都應(yīng)該自動(dòng)的被衍生出。
actions 是唯一能夠改變 state 的方法。
state 是最基礎(chǔ)的數(shù)據(jù),它不應(yīng)該包含冗余的和派生的數(shù)據(jù)。
computed values 派生值是通過(guò)純函數(shù)從 state 中派生而來(lái)的。當(dāng)派生值依賴的狀態(tài)發(fā)生變化了,Mobx 將會(huì)自動(dòng)更新派生值。如果依賴的狀態(tài)沒(méi)有改變,mobx 會(huì)做優(yōu)化處理。
reactions 也是派生數(shù)據(jù),是從 state 中派生而來(lái)的。它的副作用是自動(dòng)更新 UI。(注:mobx 有一個(gè) reaction 接口,當(dāng) state 改變時(shí),就會(huì)調(diào)用它的回調(diào)。UI 是通過(guò) reaction 更新的。)
React 和 MobX 是非常強(qiáng)大的組合。React 提供了將應(yīng)用狀態(tài)映射為可渲染的組件樹(shù)的機(jī)制。MobX 提供存儲(chǔ)和更新應(yīng)用狀態(tài)的機(jī)制,供 React 使用。
React 和 MobX 提供了開(kāi)發(fā)過(guò)程中常見(jiàn)問(wèn)題的解決方案。 React 通過(guò)使用虛擬 DOM,減少了對(duì)瀏覽器 DOM 的操作。MobX 通過(guò)使用了響應(yīng)式虛擬依賴狀態(tài)圖(reactive virtual dependency state graph) ,提供了應(yīng)用程序狀態(tài)與 React 組件同步的機(jī)制,這樣 state 只會(huì)在需要時(shí)更新才會(huì)更新。(譯者注:這段有點(diǎn)難理解,大概的意思是 Mobx 關(guān)注的是 store 到 state 的過(guò)程,React 關(guān)注的是 state 到 view 的過(guò)程)。
輔助函數(shù)在實(shí)際開(kāi)發(fā)中,需要用到不少 mobx 的輔助函數(shù),這些輔助函數(shù)一共 14 個(gè),挑了一些列舉如下。
autorun
observable 的值初始化或改變時(shí),自動(dòng)運(yùn)行。
trasaction
批量改變時(shí),通過(guò) trasaction 包裝,只會(huì)觸發(fā)一次 autorun。
extendsObservable
對(duì)類(lèi)的屬性或?qū)嵗M(jìn)行監(jiān)聽(tīng)。
observable
對(duì)普通對(duì)象進(jìn)行監(jiān)聽(tīng)。
map
使用 asMap 將對(duì)象轉(zhuǎn)化為 map。
action-strict
在 mobx.usrStrict(true)時(shí),只能通過(guò) action 觸發(fā)值的改變。
when
類(lèi)似 autorun.
mobx.when 第一個(gè)參數(shù)是一個(gè)函數(shù),初始化時(shí)也會(huì)自動(dòng)執(zhí)行。該函數(shù)返回一個(gè) boolean 值,當(dāng)返回值為 true 的時(shí)候,才會(huì)繼續(xù)觸發(fā)第一個(gè)函數(shù)。當(dāng)返回值為 flase 時(shí),不再繼續(xù)監(jiān)聽(tīng)。這時(shí)會(huì)執(zhí)行 mobx.when 的第二個(gè)參數(shù),這個(gè)參數(shù)也是一個(gè)函數(shù)。
reaction
類(lèi)似 autorun.
reaction 不會(huì)在初始化時(shí)執(zhí)行,只會(huì)在值改變的時(shí)候執(zhí)行。
該函數(shù)有 2 個(gè)值,第一個(gè)參數(shù)是一個(gè)函數(shù),返回監(jiān)聽(tīng)的值.
第二個(gè)參數(shù),也是一個(gè)函數(shù),會(huì)在值改變的時(shí)候執(zhí)行。
spy
類(lèi)似 aoturun.
監(jiān)聽(tīng)所有 mobx 的事件。
包含一個(gè) type ,該值用來(lái)區(qū)分執(zhí)行事件的類(lèi)型。
whyRun
用于調(diào)試,打印 autorun 為什么會(huì)觸發(fā)。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/86674.html
摘要:我現(xiàn)在寫(xiě)的這些是為了解決和這兩個(gè)狀態(tài)管理庫(kù)之間的困惑。這甚至是危險(xiǎn)的,因?yàn)檫@部分人將無(wú)法體驗(yàn)和這些庫(kù)所要解決的問(wèn)題。這肯定是要第一時(shí)間解決的問(wèn)題。函數(shù)式編程是不斷上升的范式,但對(duì)于大部分開(kāi)發(fā)者來(lái)說(shuō)是新奇的。規(guī)模持續(xù)增長(zhǎng)的應(yīng) 原文地址:Redux or MobX: An attempt to dissolve the Confusion 原文作者:rwieruch 我在去年大量的使用...
摘要:想學(xué)習(xí)下全家桶中的,剛好看到了阮一峰老師的入門(mén)文章,受益匪淺。官方的解釋是是容器,提供可預(yù)測(cè)化的狀態(tài)管理。和,寓意為派遣。這是發(fā)出的唯一方法。另外方法會(huì)返回一個(gè)函數(shù),我們?nèi)绻獬O(jiān)聽(tīng),就可以調(diào)用這個(gè)函數(shù)。 背景 我:您好!我對(duì)此職位感興趣,可以聊聊嗎? 招聘者:您好!感謝關(guān)注。方便發(fā)一份您的簡(jiǎn)歷嗎? 幾分鐘后。。。 招聘者:請(qǐng)過(guò)用過(guò)react嗎? 我:只看過(guò)一些項(xiàng)目,...
摘要:它是由一個(gè)非常聰明的人開(kāi)發(fā)的,用來(lái)緩解在單頁(yè)面應(yīng)用中管理狀態(tài)的問(wèn)題。的問(wèn)題沒(méi)有一種適合所有場(chǎng)景的完美工具。為設(shè)計(jì)的是世界的另一個(gè)新增內(nèi)容,但目前僅適用于。這將導(dǎo)致最后期限延長(zhǎng),并且留下更多需要我們維護(hù)的代碼。 原文:The Problems with Redux: Can React, MobX, and Realm save us? 作者:Erich Reich 首先,我不討厭 ...
摘要:簡(jiǎn)介是一個(gè)狀態(tài)管理的庫(kù),由基礎(chǔ)上開(kāi)發(fā)出來(lái),與的主要區(qū)別是只有一個(gè),關(guān)于,后文會(huì)詳述。這個(gè)函數(shù)接受四個(gè)參數(shù),它們分別是,,和。之前在注冊(cè)頁(yè)面,如果沒(méi)有滿足相關(guān)條件,則觸發(fā)的行為。具體定義了項(xiàng)目中觸發(fā)的行為類(lèi)別,通過(guò)屬性來(lái)區(qū)別于不同的行為。 redux簡(jiǎn)介 redux是一個(gè)js狀態(tài)管理的庫(kù),由flux基礎(chǔ)上開(kāi)發(fā)出來(lái),與flux的主要區(qū)別是只有一個(gè)store,關(guān)于store,后文會(huì)詳述。在各...
閱讀 1631·2021-10-14 09:43
閱讀 5534·2021-09-07 10:21
閱讀 1279·2019-08-30 15:56
閱讀 2131·2019-08-30 15:53
閱讀 1236·2019-08-30 15:44
閱讀 2013·2019-08-30 15:44
閱讀 1323·2019-08-29 17:24
閱讀 757·2019-08-29 15:19