成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

一篇帶你揭秘 MobX 實現(xiàn)原理

開發(fā) 項目管理
mobx 是熱度僅次于 redux 的狀態(tài)管理庫,它和 redux 有相同的地方也有不同的地方。

mobx 是流行的狀態(tài)管理庫,熱度僅次于 redux。它和 redux 有的地方一樣,也有的地方不一樣:

一樣的地方是 mobx 和 redux 都是單向數(shù)據(jù)流,通過 action 觸發(fā)全局 state 更新,然后通知視圖。

redux 的數(shù)據(jù)流:

mobx 的數(shù)據(jù)流:

但是它們修改狀態(tài)的方式不一樣:

redux 是每次返回一個全新的狀態(tài),一般搭配實現(xiàn)對象 immutable 的庫來用。

mobx 每次都是修改的同一個狀態(tài)對象,基于響應式代理,也就是 Object.defineProperty 代理 get、set 的處理,get 時把依賴收集起來,set 修改時通知所有的依賴做更新。和 vue2 的響應式代理很類似。

其中,redux 那種方式是函數(shù)式的思路,所以狀態(tài)的修改都在一個個 reducer 函數(shù)里,而 mobx 那種方式則是面向對象的代理的思路,所以很容易把 state 組織成一個個 class。

這也就導致了兩種狀態(tài)管理方式的代碼組織是有區(qū)別的:

redux 是在 reducer 函數(shù)里組織狀態(tài)(函數(shù)式的特點):

const reducer = (state = 0, action) => {
switch (action.type) {
case 'INCREMENT': return state + 1;
case 'DECREMENT': return state - 1;
default: return state;
}
};

而 mobx 則是在 class 里組織狀態(tài)(面向對象的特點):

import {observable, action} from 'mobx';
class Store {
@observable number = 0;
@action add = () => {
this.number++;
}
}

此外,redux 那種方式每次都要返回一個新的對象,雖然可以用 immutable 的庫來減少創(chuàng)建新對象的開銷,但是比起 mobx 直接修改原對象來說,開銷還是大一點。

而且 redux 通知依賴更新的時候是全部通知的,而 mobx 因為收集了每個屬性的依賴,可以精準的通知。

所以 mobx 的性能會比 redux 高一些。

綜上,mobx 和 redux 都是單向數(shù)據(jù)流,但是管理狀態(tài)的思路上,一個是函數(shù)式的思想,通過 reducer 函數(shù)每次返回新的 state,一個是面向對象的思想,通過響應式對象來管理狀態(tài),這導致了狀態(tài)組織方式上的不同(function/class),而且 redux 創(chuàng)建新的 state 的開銷還有通知所有依賴的開銷都比 mobx 大,性能比 mobx 差一些。

對比下來,我們會發(fā)現(xiàn) mobx 似乎比 redux 優(yōu)秀一些。那我們具體看下 mobx 怎么用吧:

mobx 的使用

官方提供的 demo 是這樣的:

import React from "react"
import ReactDOM from 'react-dom';
import { makeAutoObservable } from "mobx"
import { observer } from "mobx-react"
class Timer {
secondsPassed = 0
constructor() {
makeAutoObservable(this)
}
increase() {
this.secondsPassed += 1
}
reset() {
this.secondsPassed = 0
}
}
const myTimer = new Timer()
const TimerView = observer(({ timer }) => (
<button onClick={() => timer.reset()}>Seconds passed: {timer.secondsPassed}</button>
))
setInterval(() => {
myTimer.increase()
}, 1000);
ReactDOM.render(<TimerView timer={myTimer} />, document.getElementById('root'));

就像前面說的,mobx 基于響應式對象來管理狀態(tài),所以組織狀態(tài)是用 class 的形式。

我們聲明了 Timer 的 class,有一個屬性是 secondsPassed 代表過去了幾秒,有兩個方法來修改它。

在構造器里調用 makeAutoObservable 來創(chuàng)建響應式的代理。

然后 new 一個 Timer 的對象,傳到組件里,組件使用 observer 的高階組件包裹,它負責把被包裹的組件添加到 timer 的響應式依賴中去。

然后把這個組件渲染到 dom。

這樣就完成了 mobx 和 react 的結合使用,看下效果:

我們是把時間(secondsPassed)放在 mobx 的全局 state 中管理的,在組件里使用,然后定時更新它。發(fā)現(xiàn)每次更新組件都得到了通知并做了渲染,這就是全局狀態(tài)管理的功能。

demo 里我們用的 makeAutoObservable 函數(shù),它會自動給屬性添加響應式代理,方法會添加一層觸發(fā) action 的代理。

也可以手動標識:

import { observable, action } from "mobx"
class Timer {
@observable secondsPassed = 0
constructor() {
}
@action increase() {
this.secondsPassed += 1
}
@action reset() {
this.secondsPassed = 0
}
}

我們大概知道了 mobx 怎么用,那它是怎么實現(xiàn)的呢?

接下來我們從源碼來理一下它的實現(xiàn)原理:

mobx 的實現(xiàn)原理

首先,mobx 會對對象做響應式代理,那代理以后的對象是什么樣的呢?

我們打印下:

原始對象的 secondsPassed 屬性是 0,increase 和 reset 方法體修改 secondsPassed 的值。

而代理以后的對象屬性分為了 get 和 set,并且實現(xiàn)變成了 this[$mobx].getObservablePropValue 和 setObservablePropValue,這明顯是做了響應式的處理了。

代理以后的方法都變成了 excuteAction,執(zhí)行方法會 dispatch 一個 acition。

那這個響應式的代理是怎么實現(xiàn)的呢?

跟蹤 makeAutoObservable 的源碼會發(fā)現(xiàn) mobx 創(chuàng)建了一個 ObservableObjectAdministration 的對象放到了 $mobx 屬性上。

在 timer 對象確實是有這個屬性的:

用 Symbol 聲明了一個私有屬性 mobx administration 來放 ObservableObjectAdministration 對象。

然后還用 Symbol 聲明了一個私有屬性。mobx-keys 來放所有做了代理的屬性和方法名。

那這個 ObservableObjectAdministration 對象是干啥的呢?

看下它的定義:

可以看到它有 values 屬性記錄每個 key 的依賴。

還有 getObservableValue 和 setObservableValue 來獲取和設置某個 key 的值。這兩個方法就是被代理后的屬性的 get set 最終調用的方法:

這不就串起來了么:

創(chuàng)建對象的時候 mobx 會對屬性和方法做代理,會添加一個 Symbol(mobx administrator) 屬性到對象上來保存 ObservableObjectAdministration 對象,它是用來記錄屬性的所有依賴的,對屬性的 get 和 set 都會被代理到這個 ObservableObjectAdministration 的 getXxx 和 setXxx 方法上。

我們打印下這個對象看看:

確實,values 里保存了唯一一個屬性和它的所有依賴。

至此,對對象做響應式代理的流程我們已經(jīng)理清了:

那這個依賴是什么時候收集的呢?

我們繼續(xù)往下看 get 收集依賴和 set 觸發(fā)依賴更新的部分:

我們用 observable 包裹了組件,它是一個高階組件,對組件做一層代理,返回新的組件:

在這層代理里面,創(chuàng)建了 Reaction 對象,也就是收到更新的通知之后怎么做出反應,在回調函數(shù)里用 setState([]) 的方式實現(xiàn)了強制更新。

并且,這層高階組件的代理里會把當前組件設置到全局,這樣后面做 get 的依賴收集的時候就能拿到對應的組件了。

所以在組件里用到 state 的 get,做依賴收集時,就知道當前是哪個組件了:

當然,這里收集的不是具體哪個組件,而是 onInvalidate 的回調函數(shù),也就是收到更新的通知之后如何做出反應。

這樣就完成了依賴的收集,在后面修改響應式對象的狀態(tài)屬性的時候,就會觸發(fā)依賴,然后實現(xiàn)組件的更新:

這樣,我們就串聯(lián)起了 mobx 的響應式原理:

總結

mobx 是熱度僅次于 redux 的狀態(tài)管理庫,它和 redux 有相同的地方也有不同的地方:

相同的地方是都是單向數(shù)據(jù)流。

不同的地方是 redux 是函數(shù)式思想的實現(xiàn),通過 reducer 函數(shù)管理狀態(tài),一般會用 immutable 的庫來提高創(chuàng)建新對象的性能。而 mobx 是面向對象的思想,通過響應式代理來管理狀態(tài),可以通過 class 組織 state。

性能方面 mobx 的響應式能精準的通知依賴做更新,而 redux 只能全局通知,而且 mobx 只是修改同一個對象,不是每次創(chuàng)建新對象,性能會比 redux 更高。

然后我們又通過一個 demo 來入門了下 react 中使用 mobx:通過 class 組織狀態(tài),然后創(chuàng)建響應式代理,組件用 observer 高階組件做一層包裝,傳入 mobx 的對象,這樣 mobx 和組件就結合到了一起,狀態(tài)更新就能通知到組件。

之后我們從源碼層面理清了 mobx 的響應式機制的實現(xiàn)原理:mobx 會在對象上添加一個 Symbol($mobx) 的隱藏屬性,用來放 ObservableObjectAdministration 對象,它是用于管理屬性和它的依賴的,在 get 的 時候收集依賴,然后 set 的時候就可以通知所有收集到的依賴(Reaction)做更新。

看到這里,你是否對 mobx 的特點和原理有更深的理解了呢?

責任編輯:姜華 來源: 神光的編程秘籍
相關推薦

2021-08-11 07:02:21

npm包管理器工具

2021-08-26 05:27:08

Base64 字節(jié)流算法

2022-02-18 08:54:21

docker操作系統(tǒng)Linux

2023-04-20 08:00:00

ES搜索引擎MySQL

2021-05-20 06:57:16

RabbitMQ開源消息

2021-04-08 11:00:56

CountDownLaJava進階開發(fā)

2021-08-23 06:25:57

CSS 技巧animation

2024-05-28 09:21:25

2021-06-16 08:28:25

unary 方法函數(shù)技術

2021-05-17 05:51:31

KubeBuilderOperator測試

2021-05-18 05:40:27

kubebuilderwebhook進階

2022-02-24 07:56:42

開發(fā)Viteesbuild

2025-01-17 07:00:00

2021-05-12 06:18:19

KubeBuilderOperatork8s

2022-03-10 08:31:51

REST接口規(guī)范設計Restful架構

2021-09-07 07:34:42

CSS 技巧代碼重構

2021-05-14 16:34:12

Semaphore原理

2022-05-25 08:31:31

ArthasInstrument

2022-02-21 09:44:45

Git開源分布式

2023-05-12 08:19:12

Netty程序框架
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 一区二区三区视频在线观看 | 亚洲成人av| 国产视频二区 | 色综合99 | 成人免费观看网站 | 欧美日韩精品一区二区 | 天天艹逼网 | 国产精品一区二区视频 | 干干天天 | 久久久99精品免费观看 | 一本在线 | 在线小视频 | 日韩国产免费观看 | 欧美日韩成人影院 | 日韩和的一区二区 | 亚洲精品乱码久久久久久蜜桃91 | 久久人操| 人人干人人舔 | h视频亚洲 | 欧美在线视频网站 | 99久久精品一区二区成人 | 午夜精品 | 精品一区二区三区在线视频 | av天天看 | 国产精品99久久久久久久久久久久 | 免费在线看黄视频 | 国产精品精品久久久久久 | 理论片午午伦夜理片影院 | 日韩成人在线播放 | 天天躁天天操 | 久久影院一区 | 中文字幕一区二区三区乱码图片 | 午夜视频在线观看网站 | 91久久精品日日躁夜夜躁欧美 | 国产一区二区在线视频 | 天色综合网 | 97国产精品视频 | 日韩精品一区中文字幕 | 免费v片在线观看 | 中文字幕在线国产 | 国外激情av|