摘要:前言原本說接下來會專注學(xué)但是最新工作又學(xué)習(xí)了一些有意思的庫於是就再寫下來做個簡單的入門之前我寫過一篇文章這個也算是作為一個補充吧這次無非就是類似筆記把認(rèn)為的一些關(guān)鍵點記下來有些地方還沒用到就衹是描述一下代碼有些自己寫的有些文檔寫的很好就搬下
前言
原本說接下來會專注學(xué)nodejs,但是最新工作又學(xué)習(xí)了一些有意思的庫,於是就再寫下來做個簡單的入門,之前我寫過一篇文章,這個也算是作為一個補充吧.
這次無非就是類似筆記,把認(rèn)為的一些關(guān)鍵點記下來,有些地方還沒用到就衹是描述一下,代碼有些自己寫的,有些文檔寫的很好就搬下來,想瞭解更多可看官網(wǎng)
Mobx中文文檔
Mobx英文文檔
Github 倉庫
PS:
2018/06/11 發(fā)現(xiàn)中文版有些關(guān)鍵地方?jīng)]翻譯,補充一下observable({})/observable.object(props, decorators?, options?)部分
通過透明的響應(yīng)式編程使?fàn)顟B(tài)管理變得簡單和可擴展,背后哲學(xué)是任何源自應(yīng)用狀態(tài)的東西都應(yīng)自動獲得,(包括UI,數(shù)據(jù)序列化,服務(wù)器通訊等)
React通過提供機制把應(yīng)用狀態(tài)轉(zhuǎn)換成可渲染組件樹并對其渲染,優(yōu)化UI渲染,就是通過使用虛擬DOM減少昂貴的DOM變化數(shù)量.
Mobx提供機制來存儲和更新應(yīng)用狀態(tài)供React使用,優(yōu)化應(yīng)用狀態(tài)和React組件同步,通過使用響應(yīng)式的虛擬依賴狀態(tài)圖表,讓其在需要的時候才更新并且保持最新.
個人感覺與Redux相比除了目的一致是管理應(yīng)用狀態(tài)之外.不管是寫法還是思想都截然不同.因為才剛?cè)腴T,這裡只說用法不講區(qū)別.
官方代碼我們先看看這段代碼做了什麼,再分開詳細(xì)講解一下對應(yīng)知識點
observable(組件): 轉(zhuǎn)成響應(yīng)式組件,會自動轉(zhuǎn)換應(yīng)用狀態(tài)和更新;
get 函數(shù): 計算值,根據(jù)現(xiàn)有的狀態(tài)或其它計算值衍生出的值;
autorun函數(shù): 類似get,依賴關(guān)系改變時觸發(fā);
action: 改變狀態(tài),嚴(yán)格模式下所有修改操作都應(yīng)該在action裡面執(zhí)行;
import {observable, autorun} from "mobx"; var todoStore = observable({ /* 一些觀察的狀態(tài) */ todos: [], /* 推導(dǎo)值 */ get completedCount() { return this.todos.filter(todo => todo.completed).length; }, }); /* 觀察狀態(tài)改變的函數(shù) */ autorun(function() { console.log( "Completed %d of %d items", todoStore.completedCount, todoStore.todos.length ); }); /* ..以及一些改變狀態(tài)的動作 */ todoStore.todos[0] = { title: "Take a walk", completed: false, }; // -> 同步打印 "Completed 0 of 1 items" todoStore.todos[0].completed = true; // -> 同步打印 "Completed 1 of 1 items"
官方流程圖:
//標(biāo)準(zhǔn)用法 observable(value) //裝飾器用法 @observable classProperty = value
Observable 值可以是JS基本數(shù)據(jù)類型、引用類型、普通對象、類實例、數(shù)組和映射. 匹配類型應(yīng)用了以下轉(zhuǎn)換規(guī)則,但可以通過使用調(diào)節(jié)器進行微調(diào).
Map: 返回一個新的 Observable Map,不但對一個特定項的更改做出反應(yīng),而且對添加或刪除該項也做出反應(yīng);
數(shù)組: 會返回一個 Observable Array;
沒有原型的對象: 那么對象會被克隆并且所有的屬性都會被轉(zhuǎn)換成可觀察的;
有原型的對象: JavaSript 原始數(shù)據(jù)類型或者函數(shù),observable會拋出錯誤,如果你想要創(chuàng)建一個獨立的
observable引用例如值可以使用Boxed Observable observables.MobX 不會將一個有原型的對象自動轉(zhuǎn)換成可觀察的,因為這是它構(gòu)造函數(shù)的職責(zé).可以在constructor使用extendObservable或者類型定義使用decorate替代.
observable(new Map())/observable.map(values, options)values: 可以是對象、 數(shù)組或者字符串鍵的 ES6 map;
options:
deep: 決定分配給 observable 映射的值會否通過 observable 來傳遞使其轉(zhuǎn)變成可觀察的;
name: 調(diào)試名稱,用于 spy 或者 MobX 開發(fā)者工具;
const map = observable.map(new Map());
以下是MobX 提供方法:
toJS(): 將 observable 映射轉(zhuǎn)換成普通映射;
toJSON(): 返回此映射的淺式普通對象表示.(想要深拷貝,請使用 mobx.toJS(map));
intercept(interceptor): 可以用來在任何變化作用于映射前將其攔截;
observe(listener, fireImmediately?): 注冊偵聽器,在映射中的每個更改時觸發(fā);
merge(values): 把提供對象的所有項拷貝到映射中.values 可以是普通對象、entries 數(shù)組或者 ES6 字符串鍵的映射;
replace(values): 用提供值替換映射全部內(nèi)容.是 .clear().merge(values) 的簡寫形式;
observable([])/observable.array(values, options)這是遞歸的,所以數(shù)組中的所有(未來的)值都會是可觀察的.
options:
deep: 決定分配給 observable 映射的值會否通過 observable 來傳遞使其轉(zhuǎn)變成可觀察的;
name: 調(diào)試名稱,用于 spy 或者 MobX 開發(fā)者工具;
const ary = observable.array([1, 2, 4]);
注意:
observable.array 會創(chuàng)建一個人造數(shù)組(類數(shù)組對象)來代替真正的數(shù)組. 支持所有的原生方法,包括從索引的分配到包含數(shù)組長度.
驗證類型方法的話返回不是數(shù)組.可以通過使用 array.slice() 在 observable 數(shù)組傳遞給外部庫或者內(nèi)置方法前創(chuàng)建一份淺拷貝;
sort 和 reverse 函數(shù)實現(xiàn)不會改變數(shù)組本身,而是返回一個排序過/反轉(zhuǎn)過的拷貝;
以下是MobX 提供方法:
intercept(interceptor): 可以用來在任何變化作用于數(shù)組前將其攔截;
observe(listener, fireImmediately? = false): 監(jiān)聽數(shù)組的變化.回調(diào)函數(shù)將接收表示數(shù)組拼接或數(shù)組更改的參數(shù),它符合 ES7 提議.它返回一個清理函數(shù)以用來停止監(jiān)聽器;
clear(): 從數(shù)組中刪除所有項;
replace(newItems): 用新項替換數(shù)組中所有已存在的項;
find(predicate: (item, index, array) => boolean, thisArg?): 基本上等同于 ES7 的 Array.find 提議;
findIndex(predicate: (item, index, array) => boolean, thisArg?): 基本上等同于 ES7 的 Array.findIndex 提議;
remove(value): 通過值從數(shù)組中移除一個單個的項.如果項被找到并移除的話,返回 true ;
peek(): 和 slice() 類似,返回一個有所有值的數(shù)組并且數(shù)組可以放心的傳遞給其它庫,但是不創(chuàng)建保護性拷貝;
observable({})/observable.object(props, decorators?, options?)一個普通的 JavaScript 對象 (指不是使用構(gòu)造函數(shù)創(chuàng)建出來的對象,而是以 Object 作為其原型,或者根本沒有原型)傳遞給 observable 方法,對象的所有屬性都將被拷貝至一個克隆對象并將克隆對象轉(zhuǎn)變成可觀察的.
這是遞歸應(yīng)用的,所以如果對象的某個值是一個對象或數(shù)組,那么該值也將通過 observable 傳遞.
options:
deep: 決定分配給 observable 映射的值會否通過 observable 來傳遞使其轉(zhuǎn)變成可觀察的;
name: 調(diào)試名稱,用于 spy 或者 MobX 開發(fā)者工具;
const obj = observable.object({ key: "value"});
注意:
[MobX 4及以下]當(dāng)通過 observable 傳遞對象時,只有在把對象轉(zhuǎn)變 observable 時存在的屬性才會是可觀察的. 稍后添加到對象的屬性不會變?yōu)榭捎^察的,除非使用 set 或 extendObservable;
只有普通的對象可以轉(zhuǎn)變成 observable .對于非普通對象,構(gòu)造函數(shù)負(fù)責(zé)初始化 observable 屬性. 要么使用 @observable 注解[color=#b1b1b1](annotation,這個解釋不太懂??),要么使用 extendObservable 函數(shù);
屬性的 getter 會自動轉(zhuǎn)變成衍生屬性,就像 @computed 所做的;
observable 是自動遞歸到整個對象的.在實例化過程中和將來分配給 observable 屬性的任何新值的時候.Observable 不會遞歸到非普通對象中;
更細(xì)粒度的控制,比如哪些屬性應(yīng)該轉(zhuǎn)變成可觀察的和如何變成可觀察的,請參見裝飾器;
observable.box(value)JavaScript 中的所有原始類型值都是不可變的,因此它們都是不可觀察的,box創(chuàng)建一個基于 ref 裝飾器的箱子.這意味著箱子里的任何(將來)值都不會自動地轉(zhuǎn)換成 observable .
options:
1) name: 調(diào)試名稱,用于 spy 或者 MobX 開發(fā)者工具;
const box = observable.box("box"); box.observe(function(change) { console.log(change.oldValue, "->", change.newValue); });
以下是box提供方法:
get(): 返回當(dāng)前值;
set(value): 替換當(dāng)前存儲的值并通知所有觀察者;
intercept(interceptor): 可以用來在任何變化應(yīng)用前將其攔截;
observe(callback: (change) => void, fireImmediately = false): 注冊一個觀察者函數(shù),每次存儲值被替換時觸發(fā).返回一個函數(shù)以取消觀察者.change是一個對象,其中包含 observable 的 newValue 和 oldValue .
裝飾器定義 observable 屬性的行為,默認(rèn)為對任意鍵值對使用 observable.deep,對 getters 使用 computed .
observable: observable.deep 的別名
observable.deep: 任何 observable 都使用的默認(rèn)的調(diào)節(jié)器.它將任何(尚未成為 observable )數(shù)組,映射或純對象克隆并轉(zhuǎn)換為 observable 對象,并將其賦值給給定屬性
observable.ref: 禁用自動的 observable 轉(zhuǎn)換,只是創(chuàng)建一個 observable 引用
observable.shallow: 只能與集合組合使用. 將任何分配的集合轉(zhuǎn)換為 observable,但該集合的值將按原樣處理
observable.struct: 就像 ref, 但會忽略結(jié)構(gòu)上等于當(dāng)前值的新值
computed: 創(chuàng)建一個衍生屬性, 參見 computed
computed(options): 同 computed , 可設(shè)置選項
computed.struct: 與 computed 相同,但是只有當(dāng)視圖產(chǎn)生的值與之前的值結(jié)構(gòu)上有不同時,才通知它的觀察者
action: 創(chuàng)建一個動作, 參見 action
action(name): 創(chuàng)建一個動作,重載了名稱
action.bound: 創(chuàng)建一個動作, 并將 this 綁定到了實例
class Person { name = "John"; } // 使用 decorate 時,所有字段都應(yīng)該指定 (畢竟,類里的非 observable 字段可能會更多) decorate(Person, { name: observable, });Derivations(衍生)
任何源自狀態(tài)并且不會再有任何進一步的相互作用的東西就是衍生,衍生以多種形式存在:
用戶界面
衍生數(shù)據(jù),比如剩下的待辦事項的數(shù)量.
后端集成,比如把變化發(fā)送到服務(wù)器端.
MobX 區(qū)分兩種類型的衍生:
Computed values(計算值): 它們是永遠(yuǎn)可以使用純函數(shù)(pure function)從當(dāng)前可觀察狀態(tài)中衍生出的值;
Reactions(反應(yīng)): Reactions 是當(dāng)狀態(tài)改變時需要自動發(fā)生的副作用.需要有一個橋梁來連接命令式編程(imperative programming)和響應(yīng)式編程(reactive programming).或者說得更明確一些,它們最終都需要實現(xiàn)I / O 操作;
(@)computed計算值(computed values)是可以根據(jù)現(xiàn)有的狀態(tài)或其它計算值衍生出的值.如果你想響應(yīng)式的產(chǎn)生一個可以被其它 observer 使用的值,請使用 @computed.計算值在大多數(shù)情況下可以被 MobX 優(yōu)化的,例如:
前一個計算中使用的數(shù)據(jù)沒有更改,計算屬性將不會重新運行;
某個其它計算屬性或 reaction 未使用該計算屬性,也不會重新運行. 在這種情況下,它將被暫停;
一個計算值不再被觀察了,例如使用它的UI不復(fù)存在了,MobX 可以自動地將其垃圾回收;
注意:
計算屬性是不可枚舉的,它們也不能在繼承鏈中被覆蓋;
可以使用 observe 或 keepAlive 來強制保持計算值總是處于喚醒狀態(tài);
observable.object 和 extendObservable 都會自動將 getter 屬性推導(dǎo)成計算屬性;
如果計算值在其計算期間拋出異常,則此異常將捕獲并在讀取其值時重新拋出. 強烈建議始終拋出“錯誤”,以便保留原始堆棧跟蹤. 拋出異常不會中斷跟蹤,所有計算值可以從異常中恢復(fù).
計算值的 setter:
不能用來直接改變計算屬性的值,但是它們可以用來作“逆向”衍生.就是反向計算;
必須在 getter 之后定義 setter,一些 TypeScript 版本會知道聲明了兩個具有相同名稱的屬性;
這是一個自動的動作,只需要直接使用set xx(){};
class Test { @observable num = 0; @computed get total() { return this.num * 10; } set total(value) { this.num = value / 10; } } //OR const Test = observable.object({ num: 0; get total() { return this.num * 10; } set total(value) { this.num = value / 10; } })computed(expression,options) 函數(shù)用法
某些情況下,你需要傳遞一個“在box中”的計算值時,它可能是有用的.
options:
name: 調(diào)試名稱,用于 spy 或者 MobX 開發(fā)者工具;
context: 在提供的表達式中使用的 this;
set: 要使用的setter函數(shù). 沒有 setter 的話無法為計算值分配新值. 如果傳遞給 computed 的第二個參數(shù)是一個函數(shù),那么就把會這個函數(shù)作為 setter;
equals: 默認(rèn)值是 comparer.default .它充當(dāng)比較函數(shù).如果前后值相等,那么觀察者就不會重新評估;
requiresReaction: 對于非常昂貴的計算值,推薦設(shè)置成 true .如果你嘗試讀取它的值,但某些觀察者沒有跟蹤該值(在這種情況下,MobX 不會緩存該值),則會導(dǎo)致計算結(jié)果丟失,而不是進行昂貴的重新評估;
keepAlive: 如果沒有任何人觀察到,則不要使用此計算值. 請注意,這很容易導(dǎo)致內(nèi)存泄漏,因為它會導(dǎo)致此計算值使用的每個 observable ,并將計算值保存在內(nèi)存中;
MobX 提供了三個內(nèi)置 comparer (比較器) :
comparer.identity: 使用恒等 (===) 運算符來判定兩個值是否相同;
comparer.default: 等同于 comparer.identity,但還認(rèn)為 NaN 等于 NaN ;
comparer.structural: 執(zhí)行深層結(jié)構(gòu)比較以確定兩個值是否相同;
const box = observable("box"), upperCaseName = computed(() => name.get().toUpperCase()), disposer = upperCaseName.observe(change => console.log(change.newValue)); box.set("Dave");Autorun(expression,options)
創(chuàng)建一個響應(yīng)式函數(shù),而該函數(shù)本身永遠(yuǎn)不會有觀察者,調(diào)用后將接收一個參數(shù),即當(dāng)前 reaction(autorun),可用于在執(zhí)行期間清理 autorun. 當(dāng)使用 autorun 時,所提供的函數(shù)總是立即被觸發(fā)一次,然后每次它的依賴關(guān)系改變時會再次被觸發(fā),相比之下computed(function)創(chuàng)建的函數(shù)只有當(dāng)它有自己的觀察者時才會重新計算,否則它的值會被認(rèn)為是不相關(guān)的;
options:
delay: 可用于對效果函數(shù)進行去抖動的數(shù)字(以毫秒為單位).如果是 0(默認(rèn)值) 的話,那么不會進行去抖.
name: 調(diào)試名稱,用于 spy 或者 MobX 開發(fā)者工具;
onError: 用來處理 reaction 的錯誤,而不是傳播它們;
scheduler: 設(shè)置自定義調(diào)度器以決定如何調(diào)度 autorun 函數(shù)的重新運行;
var numbers = observable([1, 2, 3]); var sum = computed(() => numbers.reduce((a, b) => a + b, 0)); var disposer = autorun(() => console.log(sum.get())); // 輸出 "6" numbers.push(4); // 輸出 "10" disposer(); //清理 autorun numbers.push(5); // 不會再輸出任何值.`sum` 不會再重新計算.when(predicate: () => boolean, effect?: () => void, options?)
when 觀察并運行給定的 predicate,直到返回true. 一旦返回 true,給定的 effect 就會被執(zhí)行,然后 autorunner(自動運行程序) 會被清理. 該函數(shù)返回一個清理器以提前取消自動運行程序.
class MyResource { constructor() { when( // 一旦... () => !this.isVisible, // ... 然后 () => this.dispose() ); } @computed get isVisible() { // 標(biāo)識此項是否可見 } dispose() { // 清理 } }when-promise
如果沒提供 effect 函數(shù),when 會返回一個 Promise .它與 async / await 可以完美結(jié)合.
async function() { await when(() => that.isVisible) // 等等.. }reaction(() => data, (data, reaction) => { sideEffect }, options?)
第一個數(shù)據(jù)函數(shù)是用來追蹤并返回數(shù)據(jù)作為第二個作用函數(shù)的入?yún)? 不同于 autorun 的是當(dāng)創(chuàng)建時函數(shù)不會直接運行,只有在數(shù)據(jù)表達式首次返回一個新值后才會運行. 在執(zhí)行作用函數(shù)時訪問的任何 observable 都不會被追蹤.
reaction 返回一個清理函數(shù),接收兩個參數(shù),即當(dāng)前的 reaction,可以用來在執(zhí)行期間清理 reaction .
options:
fireImmediately: 布爾值,用來標(biāo)識效果函數(shù)是否在數(shù)據(jù)函數(shù)第一次運行后立即觸發(fā).默認(rèn)值是 false,如果一個布爾值作為傳給 reaction 的第三個參數(shù),那么它會被解釋為 fireImmediately 選項;
delay: 可用于對效果函數(shù)進行去抖動的數(shù)字(以毫秒為單位).如果是 0(默認(rèn)值) 的話,那么不會進行去抖;
equals: 默認(rèn)值是 comparer.default .它充當(dāng)比較函數(shù).如果前后值相等,那么觀察者就不會重新評估;
name: 調(diào)試名稱,用于 spy 或者 MobX 開發(fā)者工具;
onError: 用來處理 reaction 的錯誤,而不是傳播它們;
scheduler: 設(shè)置自定義調(diào)度器以決定如何調(diào)度 autorun 函數(shù)的重新運行:
const todos = observable([ { title: "test1" }, { title: "test2" } ]); //會對長度變化作出反應(yīng) reaction(() => todos.length, length => console.log("reaction 1:", todos.map(todo => todo.title).join(", "))); //會對某個 todo 的 title 變化作出反應(yīng) reaction(() => todos.map(todo => todo.title), titles => console.log("reaction 2:", titles.join(", "))); // autorun 對它函數(shù)中使用的任何東西作出反應(yīng) autorun(() => console.log("autorun:", todos.map(todo => todo.title).join(", "))); // 輸出: // autorun: test1 action(() => { todos.push({title: "test3"}); })() // 輸出: // autorun: test1, test2, test3 // reaction 2: test1, test2, test3 // reaction 1: test1, test2, test3 action(() => { todos[1].title = "test4"; })() // 輸出: // autorun: test1, test4, test3 // reaction 2: test1, test4, test3@observer
observer 函數(shù)/裝飾器可以用來將 React 組件/無狀態(tài)函數(shù)組件轉(zhuǎn)變成響應(yīng)式組件. 它用 mobx.autorun 包裝了組件的 render 函數(shù)以確保任何組件渲染中使用的數(shù)據(jù)變化時都可以強制刷新組件.
observer 是由多帶帶的 mobx-react 包提供的.確保 observer 是最深處(第一個應(yīng)用)的裝飾器,否則它可能什么都不做;
如果傳遞給組件的數(shù)據(jù)是響應(yīng)式的,observer還可以防止當(dāng)組件的 props 只是淺改變時的重新渲染,這個行為與 React PureComponent 相似,不同在于這里的 state 的更改仍然會被處理. 如果一個組件提供了它自己的 shouldComponentUpdate,這個方法會被優(yōu)先調(diào)用;
import {observer} from "mobx-react"; var timerData = observable({ secondsPassed: 0 }); setInterval(() => { timerData.secondsPassed++; }, 1000); @observer class Timer extends React.Component { render() { return (Seconds passed: { this.props.timerData.secondsPassed } ) } }; //OR const Timer = observer(({ timerData }) => Seconds passed: { timerData.secondsPassed } );可觀察的局部組件狀態(tài)
@observer class Timer extends React.Component {
@observable secondsPassed = 0
componentWillMount() {
setInterval(() => {
this.secondsPassed++
}, 1000)
}
render() {
return (Seconds passed: { this.secondsPassed } )
}
}
在React組件上引入可觀察屬性. 這意味著你可以在組件中擁有功能同樣強大的本地狀態(tài)(local state),而不需要通過 React 的冗長和強制性的 setState 機制來管理. 響應(yīng)式狀態(tài)會被 render 提取調(diào)用,但不會調(diào)用其它 React 的生命周期方法,除了 componentWillUpdate 和 componentDidUpdate . 如果你需要用到其他 React 生命周期方法 ,只需使用基于 state 的常規(guī) React API 即可.
inject組件連接storesconst App = () =>提供生命週期componentWillReact; const Button = inject("colors")(observer(({ colors, label }) =>
當(dāng)組件重新渲染時被觸發(fā),這使得它很容易追溯渲染并找到導(dǎo)致渲染的操作(action).
不接收參數(shù);
初始化渲染前不會觸發(fā) (使用 componentWillMount 替代);
對于 mobx-react@4+, 當(dāng)接收新的 props 時并在 setState 調(diào)用后會觸發(fā)此鉤子;
action (動作)action(fn)
action(name, fn)
@action classMethod() {}
@action(name) classMethod () {}
@action boundClassMethod = (args) => { body }
@action(name) boundClassMethod = (args) => { body }
@action.bound classMethod() {}
action可以是任何用來修改狀態(tài)的東西,只執(zhí)行查找,過濾器等函數(shù)不應(yīng)該被標(biāo)記為action,以允許 MobX 跟蹤它們的調(diào)用.可以有助于更好的組織代碼.
action.bound自動地將動作綁定到目標(biāo)對象.與 action 不同的是不需要一個name參數(shù),名稱將始終基于動作綁定的屬性.
因為箭頭函數(shù)已經(jīng)是綁定過的并且不能重新綁定,所以不能一起使用
class Ticker { @observable tick = 0 @action.bound increment() { this.tick++ // "this" 永遠(yuǎn)都是正確的 } }編寫異步 Actions
action 包裝/裝飾器只會對當(dāng)前運行的函數(shù)作出反應(yīng),而不會對當(dāng)前運行函數(shù)所調(diào)用的函數(shù)(不包含在當(dāng)前函數(shù)之內(nèi))作出反應(yīng)! 這意味著如果 action 中存在 setTimeout、promise 的 then 或 async 語句,并且在回調(diào)函數(shù)中某些狀態(tài)改變了,那么這些回調(diào)函數(shù)也應(yīng)該包裝在 action 中.
錯誤寫法,拋出異常
class TrafficLight { @observable status = "yellow" // "red" / "green" / "yellow" @action fetchProjects() { this.status = "yellow" toggleLight().then( res => { this.status = "green" }, err => { this.status = "red" } ) } }
//包裝修復(fù)在action
class TrafficLight { @observable status = "yellow" // "red" / "green" / "yellow" @action handleAjax() { this.status = "yellow" toggleLight().then( this.handleSuc, this.handleErr ) } @action.bound handleSuc(res){ this.status = "green" } @action.bound handleErr(err){ this.status = "red" } }
//另一種內(nèi)嵌寫法
class TrafficLight { @observable status = "yellow" // "red" / "green" / "yellow" @action handleAjax() { this.status = "yellow" toggleLight().then( action("handleSuc",res => { this.status = "green" }), action("handleErr",res => { this.status = "red" }) ) } }
runInAction(name?, thunk)
runInAction 是個簡單的工具函數(shù),它接收代碼塊并在(異步的)動作中執(zhí)行.這對于即時創(chuàng)建和執(zhí)行動作非常有用.
class TrafficLight { @observable status = "yellow" // "red" / "green" / "yellow" @action handleAjax() { this.status = "yellow" toggleLight().then( runInAction(res => { this.status = "green" }), runInAction(res => { this.status = "red" }) ) } }
async / await
async / await 只是圍繞基于 promise 過程的語法糖. 結(jié)果是 @action 僅應(yīng)用于代碼塊,直到第一個 await . 在每個 await 之后,一個新的異步函數(shù)將啟動,所以在每個 await 之后,狀態(tài)修改代碼應(yīng)該被包裝成動作.
class TrafficLight { @observable status = "yellow" // "red" / "green" / "yellow" @action async handleAjax() { this.status = "yellow" toggleLight().then( try{ const result = await dosometings(); runInAction(res => { this.status = result; }), }catch(err){ runInAction(res => { this.status = "red"; }) } ) } }
flow內(nèi)置概念
優(yōu)點是它在語法上基本與 async / await 是相同的 (只是關(guān)鍵字不同),并且不需要手動用 @action 來包裝異步代碼,這樣代碼更簡潔.
class TrafficLight { @observable status = "yellow" // "red" / "green" / "yellow" @action handleAjax = flow(function* () { this.status = "yellow" toggleLight().then( try{ const result = yield dosometings(); this.status = result; }catch(err){ this.status = "red"; } ) }) }工具 API
這些 API 都是響應(yīng)式的,這意味著如果使用 set 進行添加,使用 values 或 keys 進行迭代,即便是新屬性的聲明都可以被 MobX 檢測到.
values(thing): 將集合中的所有值作為數(shù)組返回;
keys(thing): 將集合中的所有鍵作為數(shù)組返回;
set(thing, key, value)/set(thing, { key: value }): 使用提供的鍵值對來更新給定的集合;
remove(thing, key): 從集合中移除指定的項.用于數(shù)組拼接;
has(thing, key): 如果集合中存在指定的 observable 屬性就返回 true;
get(thing, key): 返回指定鍵下的子項;
import { get, set, observable, values } from "mobx" const twitterUrls = observable.object({ "John": "twitter.com/johnny" }) autorun(() => { console.log(get(twitterUrls, "Sara")) // get 可以追蹤尚未存在的屬性 }) autorun(() => { console.log("All urls: " + values(twitterUrls).join(", ")) }) set(twitterUrls, { "Sara" : "twitter.com/horsejs"})Mobx工具函數(shù)
不想摘抄了,看文檔吧...
Mobx工具函數(shù)
不想摘抄了,看文檔吧...
Mobx貼士與技巧
(更多內(nèi)容請自行查閱,本節(jié)到此為止了.)
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/106473.html
摘要:將注意力集中保持在核心庫,而將其他功能如路由和全局狀態(tài)管理交給相關(guān)的庫。此示例使用類似的語法,稱為。執(zhí)行更快,因為它在編譯為代碼后進行了優(yōu)化?;诘哪0迨沟脤⒁延械膽?yīng)用逐步遷移到更為容易。 前言 因為沒有明確的界定,這里不討論正確與否,只表達個人對前端MV*架構(gòu)模式理解看法,再比較React和Vue兩種框架不同.寫完之后我知道這文章好水,特別是框架對比部分都是別人說爛的,而我也是打算把...
摘要:它采用集中式存儲管理應(yīng)用的所有組件的狀態(tài),并以相應(yīng)的規(guī)則保證狀態(tài)以一種可預(yù)測的方式發(fā)生變化。寫需要的組件創(chuàng)建一個組件,懟下面的內(nèi)容,你喜歡彬哥哪一點創(chuàng)建一個展示組件我喜歡彬哥打開,刪掉沒用的東西,直接懟下面的代碼,到這里,架子就搭好了。 通過本文你將: 1.知道什么是Vuex. 2.知道為什么要用Vuex. 3.能跑一個Vuex的例子。 4.了解相關(guān)概念,面試的時候能說出一個所以然 5...
摘要:它采用集中式存儲管理應(yīng)用的所有組件的狀態(tài),并以相應(yīng)的規(guī)則保證狀態(tài)以一種可預(yù)測的方式發(fā)生變化。這需要對短期和長期效益進行權(quán)衡。改變中的狀態(tài)的唯一途徑就是顯式地提交。在里使用進行延遲執(zhí)行。上下文對象,這里你可以理解稱本身。 這篇文章主要介紹了Vuex入門到上手教程,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧 一、前言 當(dāng)我們的應(yīng)用遇到多個組件共享狀態(tài)時,會需...
閱讀 1025·2021-11-22 13:52
閱讀 936·2019-08-30 15:44
閱讀 580·2019-08-30 15:43
閱讀 2436·2019-08-30 12:52
閱讀 3484·2019-08-29 16:16
閱讀 645·2019-08-29 13:05
閱讀 2951·2019-08-26 18:36
閱讀 2006·2019-08-26 13:46