国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

React 狀態(tài)管理庫: Mobx

liujs / 2725人閱讀

摘要:關(guān)心性能的情況下,需要手動(dòng)設(shè)置這時(shí)就需要引入狀態(tài)管理庫。現(xiàn)在常用的狀態(tài)管理庫有和,本文會(huì)重點(diǎn)介紹,然后會(huì)將和進(jìn)行對(duì)比,最后展望下未來的狀態(tài)管理方面趨勢。如果在任何地方都修改可觀察數(shù)據(jù),將導(dǎo)致頁面狀態(tài)難以管理。

React 是一個(gè)專注于視圖層的庫。React 維護(hù)了狀態(tài)到視圖的映射關(guān)系,開發(fā)者只需關(guān)心狀態(tài)即可,由 React 來操控視圖。

在小型應(yīng)用中,多帶帶使用 React 是沒什么問題的。但在復(fù)雜應(yīng)用中,容易碰到一些狀態(tài)管理方面的問題,如:

React 只提供了在內(nèi)部組件修改狀態(tài)的接口 setState。導(dǎo)致數(shù)據(jù)、業(yè)務(wù)邏輯和視圖層耦合在組件內(nèi)部,不利于擴(kuò)展和維護(hù)。

React 應(yīng)用即一顆組件樹。兄弟節(jié)點(diǎn),或者不在同一樹杈的節(jié)點(diǎn)之間的狀態(tài)同步是非常麻煩。

關(guān)心性能的情況下,需要手動(dòng)設(shè)置 shouldComponentUpdate

這時(shí)就需要引入狀態(tài)管理庫。現(xiàn)在常用的狀態(tài)管理庫有 Mobx 和 Redux,本文會(huì)重點(diǎn)介紹 Mobx,然后會(huì)將 Mobx 和 Redux 進(jìn)行對(duì)比,最后展望下未來的 React 狀態(tài)管理方面趨勢。

Mobx 簡介

Mobx 的理念非常簡單,可以用一個(gè) demo 就把其核心原理說清楚。Mobx/MobxReact 中有三個(gè)核心概念,observableobserveraction。為了簡單起見,本文沒有提及 computed 等概念。

observable: 通過 observable(state) 定義組件的狀態(tài),包裝后的狀態(tài)是一個(gè)可觀察數(shù)據(jù)(Observable Data)。

observer: 通過 observer(ReactComponent) 定義組件。

action: 通過 action 來修改狀態(tài)。

簡化圖如下:

只講概念還比較模糊,下面給大家舉個(gè)例子。

點(diǎn)擊運(yùn)行 https://jsfiddle.net/jhwleo/1L5jcykr/9/

// 通過 observable 定義組件的狀態(tài)
const user = mobx.observable({
    name: "Jay",
     age: 22
})

// 通過 action 定義如何修改組件的狀態(tài)
const changeName = mobx.action(name => user.name = name)
const changeAge = mobx.action(age => user.age = age)

// 通過 observer 定義 ReactComponent 組件。
const Hello = mobxReact.observer(class Hello extends React.Component {
        componentDidMount(){
            // 視圖層通過事件觸發(fā) action
        changeName("Wang") // render Wang
    }

    render() {
                // 渲染
            console.log("render",user.name);
        return 
Hello,{user.name}!
} }) ReactDOM.render(, document.getElementById("mount")); // 非視圖層事件觸發(fā),外部直接觸發(fā) action changeName("Wang2")// render Wang2 // 重點(diǎn):沒有觸發(fā)重新渲染 // 原因:Hello 組件并沒有用到 `user.age` 這個(gè)可觀察數(shù)據(jù) changeAge("18") // no console

例子看完了,是不是非常簡單。

使用 Mobx,組件狀態(tài)可以在外部定義(也可以在組件內(nèi)部),因此,數(shù)據(jù)、業(yè)務(wù)邏輯可以輕易地和視圖層分離,提高應(yīng)用的可擴(kuò)展性和可維護(hù)性。另外,由于組件狀態(tài)可以在外部定義,兄弟節(jié)點(diǎn)之間的狀態(tài)同步也非常容易。最后一點(diǎn), Mobx 知道什么時(shí)候應(yīng)該渲染頁面,因此基本不需要手動(dòng)設(shè)置 shouldComponentUpdate 來提高應(yīng)用性能。

接下來給大家介紹下 Mobx 中 observable observer action 的用法,并會(huì)簡單介紹一下其原理。

observable

Mobx 如此簡單的原因之一,就是使用了可觀察數(shù)據(jù)(Observable Data)。簡單說,可觀察數(shù)據(jù)就是可以觀察到數(shù)據(jù)的讀取、寫入,并進(jìn)行攔截。

Mobx 提供了 observable 接口來定義可觀察數(shù)據(jù)。定義的可觀察數(shù)據(jù),通常也是組件的狀態(tài)。該方法接收一個(gè)參數(shù),參數(shù)可以是原始數(shù)據(jù)類型、普通 Object、Array、或者 ES6 中的 Map 類型,返回一個(gè) observable 類型的參數(shù)。

Array.isArray(mobx.observable([1,2,3])) === false // true
mobx.isObservable(mobx.observable([1,2,3])) === true // true

注意,數(shù)組經(jīng)過 observable 包裝后,就不是 Array 類型了,而是 Mobx 定義的一個(gè)特殊類型 ———— observable 類型。observable 類型,可以通過 mobx.isObservable 來檢查。

雖然數(shù)據(jù)類型不一樣,但是使用方式基本和原來一致(原始數(shù)據(jù)類型除外)。

const observableArr =  mobx.observable([1,2,3]);
const observableObj =  mobx.observable({name: "Jay"});
const observableMap =  mobx.observable(new Map([["name","Wang"]]));

console.log(observableArr[0])  // 1
console.log(observableObj.name)  // Jay
console.log(observableMap.get("name"))  // Wang

可觀察數(shù)據(jù)類型的原理是,在讀取數(shù)據(jù)時(shí),通過 getter 來攔截,在寫入數(shù)據(jù)時(shí),通過setter 來攔截。

Object.defineProperty(o, key, {
  get : function(){
        // 收集依賴的組件
    return value;
  },
  set : function(newValue){
        // 通知依賴的組件更新
        value = newValue
  },
});

在可觀察數(shù)據(jù)被組件讀取時(shí),Mobx 會(huì)進(jìn)行攔截,并記錄該組件和可觀察數(shù)據(jù)的依賴關(guān)系。在可觀察數(shù)據(jù)被寫入時(shí),Mobx 也會(huì)進(jìn)行攔截,并通知依賴它的組件重新渲染。

observer

observer 接收一個(gè) React 組件作為參數(shù),并將其轉(zhuǎn)變成響應(yīng)式(Reactive)組件。

// 普通組件
const Hello = mobxReact.observer(class Hello extends React.Component {
    render() {
        return 
Hello,{user.name}!
} }) // 函數(shù)組件 const Hello = mobxReact.observer( () => (
Hello,{user.name}!
))

響應(yīng)式組件,即當(dāng)且僅當(dāng)組件依賴的可觀察數(shù)據(jù)發(fā)生改變時(shí),組件才會(huì)自動(dòng)響應(yīng),并重新渲染。

在本文最開始的例子中,響應(yīng)式組件依賴了 user.name,但是沒有依賴 user.age。所以當(dāng)user.name 發(fā)現(xiàn)變化時(shí),組件更新。而 user.age 發(fā)生變化時(shí),組件沒有更新。

這里再詳細(xì)分析本文中的第一個(gè)例子:

user.name = "Wang2"http:// render Wang2
// 重點(diǎn):沒有觸發(fā)重新渲染
// 原因:Hello 組件并沒有用到 `user.age` 這個(gè)可觀察數(shù)據(jù)
user.age = "18"  // no console

當(dāng)可觀察數(shù)據(jù)變化時(shí),Mobx 會(huì)調(diào)用 forceUpdate 直接更新組件。

源碼地址

而在傳統(tǒng) React 應(yīng)用中,當(dāng)狀態(tài)、屬性變化后會(huì)先調(diào)用 shouldComponentUpdate,該方法會(huì)深層對(duì)比前后狀態(tài)和屬性是否發(fā)生改變,再確定是否更新組件。

shouldComponentUpdate 是很消耗性能的。Mobx 通過可觀察數(shù)據(jù),精確地知道組件是否需要更新,減少了調(diào)用 shouldComponentUpdate 這一步。這是 Mobx 性能好的原因之一。

另外需要注意的是 observer 并不是 mobx 的方法,而是 mobx-react 的方法。mobxmobx-react 關(guān)系如同 reactreact-dom

action

在 Mobx 中是可以直接修改可觀察數(shù)據(jù),來進(jìn)行更新組件的,但不建議這樣做。如果在任何地方都修改可觀察數(shù)據(jù),將導(dǎo)致頁面狀態(tài)難以管理。

所有對(duì)可觀察數(shù)據(jù)地修改,都應(yīng)該在 action 中進(jìn)行。

const changeName = mobx.action(name => user.name = name)

使用 Mobx 可以將組件狀態(tài)定義在組件外部,這樣,組件邏輯和組件視圖便很容易分離,兄弟組件之間的狀態(tài)也很容易同步。另外,也不再需要手動(dòng)使用 shouldComponentUpdate 進(jìn)行性能優(yōu)化了。

Mobx 與 Redux 對(duì)比

Mobx 的優(yōu)勢來源于可變數(shù)據(jù)(Mutable Data)和可觀察數(shù)據(jù) (Observable Data) 。

Redux 的優(yōu)勢來源于不可變數(shù)據(jù)(Immutable data)。

可觀察數(shù)據(jù)的優(yōu)勢,在前文已經(jīng)介紹過了。現(xiàn)在再來聊聊可變數(shù)據(jù)和不可變數(shù)據(jù)。

顧名思義,可變數(shù)據(jù)和不可變數(shù)據(jù)的區(qū)別在于,可變數(shù)據(jù)創(chuàng)建后可以修改,不可變數(shù)據(jù)創(chuàng)建后不可以修改。

可變數(shù)據(jù),可以直接修改,所以操作起來非常簡單。這使得使用 mobx 改變狀態(tài),變得十分簡單。

不可變數(shù)據(jù)并不一定要用到 Immutable 庫。它完全可以是一種約定,只要?jiǎng)?chuàng)建后不修改即可。比如說,Redux 中的 state。每次修改都會(huì)重新生成一個(gè) newState ,而不會(huì)對(duì)原來的值進(jìn)行改變。所以說 Redux 中的 state 就是不可變數(shù)據(jù)。

reducer(state, action) => newState.  

不可變數(shù)據(jù)的優(yōu)勢在于,它可預(yù)測,可回溯。示例代碼如下:

function foo(bar) {
  let data = { key: "value" };
  bar(data);
  console.log(data.key); // 猜猜會(huì)打印什么?
}

如果是可變數(shù)據(jù),data.key 的值可能會(huì)在 bar 函數(shù)中被改變,所以不能確定會(huì)打印什么值。但是如果是不可變數(shù)據(jù),那么就可以肯定打印值是什么。這就是不可變數(shù)據(jù)的優(yōu)勢 ———— 可預(yù)測。不可變數(shù)據(jù)不會(huì)隨著時(shí)間的變化(程序的運(yùn)行)而發(fā)生改變。在需要回溯的時(shí)候,直接獲取保存的值即可。

Mobx 與 Redux 技術(shù)選型的本質(zhì),是在可變數(shù)據(jù)與不可變數(shù)據(jù)之間選擇。具體業(yè)務(wù)場景的技術(shù)選型,還需要根據(jù)實(shí)際情況進(jìn)行分析,脫離業(yè)務(wù)場景討論技術(shù)選型是沒有意義的。但我個(gè)人在狀態(tài)管理的技術(shù)選型上,還是傾向于 Mobx 的。原因是前端與副作用打交道非常頻繁,有 Http 請求的副作用,Dom 操作的副作用等等。使用不可變數(shù)據(jù),還必須得使用中間件對(duì)副作用封裝;在 Redux 中修改一次狀態(tài),需要經(jīng)過 Action、Dispatch、Reducer 三個(gè)步驟,代碼寫起來太啰嗦;而前端的程序以中小型程序?yàn)橹鳎兒瘮?shù)帶來的可預(yù)測性的收益,遠(yuǎn)不及其帶的代碼復(fù)雜度所需要付出的成本。而 Mobx 使用起來更加簡單,更適合現(xiàn)在以業(yè)務(wù)驅(qū)動(dòng)、快速迭代的開發(fā)節(jié)奏。

展望:Mobx 與不可變數(shù)據(jù)的融合

不可變數(shù)據(jù)和可變數(shù)據(jù),都是對(duì)狀態(tài)的一種描述。那么有沒有一種方案,能將一種狀態(tài),同時(shí)用可變數(shù)據(jù)和不可變數(shù)據(jù)來描述呢?這樣就可以同時(shí)享有二者的優(yōu)勢了。(注意:當(dāng)我們說可變數(shù)據(jù)時(shí),通常它還是可觀察數(shù)據(jù),后文統(tǒng)一只說可變數(shù)據(jù)。)

答案是肯定的,它就是 MST(mobx-state-tree) https://github.com/mobxjs/mob...。

MST 是一個(gè)狀態(tài)容器:一種狀態(tài),同時(shí)包含了可變數(shù)據(jù)、不可變數(shù)據(jù)兩種不同的形式。

為了讓狀態(tài)可以在可變數(shù)據(jù)和不可變數(shù)據(jù)兩種形式之間能夠高效地相互轉(zhuǎn)化,必須遵循 MST 定義狀態(tài)的方法。

在 MST 中,定義狀態(tài)必須先定義它的結(jié)構(gòu)。狀態(tài)的結(jié)構(gòu)是一顆樹(tree),樹是由多層模型(model)組成,model 是由多個(gè)節(jié)點(diǎn)組成。

在下面的代碼中,樹只有一層 model,該 model 也只有一個(gè)節(jié)點(diǎn):title。title 的類型是事先定好的,在這里是 types.string。樹的結(jié)構(gòu)定義好后,通過 create 方法傳入數(shù)據(jù),就生成樹。

import {types} from "mobx-state-tree"

// declaring the shape of a node with the type `Todo`
const Todo = types.model({
    title: types.string
})

// creating a tree based on the "Todo" type, with initial data:
const coffeeTodo = Todo.create({
    title: "Get coffee"
})

在一些稍微復(fù)雜的例子中,樹的 model 可以有多層,每層可以有多個(gè)節(jié)點(diǎn),有些節(jié)點(diǎn)定義的是數(shù)據(jù)類型(types.xxx),有些節(jié)點(diǎn)直接定義的是數(shù)據(jù)。下面的示例中,就是定義了一個(gè)多層多節(jié)點(diǎn)的樹。除此之外,注意 types.model 函數(shù)的第一個(gè)參數(shù)定義的是 model 的名字,第二參數(shù)定義的是 model 的所有屬性,第三個(gè)參數(shù)定義的是 action。

import { types, onSnapshot } from "mobx-state-tree"

const Todo = types.model("Todo", {
    title: types.string,
    done: false
}, {
    toggle() {
        this.done = !this.done
    }
})

const Store = types.model("Store", {
    todos: types.array(Todo)
})

// create an instance from a snapshot
const store = Store.create({ todos: [{
    title: "Get coffee"
}]})

最關(guān)鍵的來了,請看下面的代碼。

// listen to new snapshots
onSnapshot(store, (snapshot) => {
    console.dir(snapshot)
})

// invoke action that modifies the tree
store.todos[0].toggle()
// prints: `{ todos: [{ title: "Get coffee", done: true }]}`

在上述代碼的第一部分,使用 onSnapshot 監(jiān)聽狀態(tài)的改變。第二部分,調(diào)用 store.todos[0].toggle() ,在這個(gè) action 中通過使用可變數(shù)據(jù)的方式,直接修改了當(dāng)前的狀態(tài)。同時(shí)在 onSnapshot 生成了一個(gè)狀態(tài)快照。這個(gè)狀態(tài)快照就是狀態(tài)的不可變數(shù)據(jù)的表現(xiàn)形式。

MST 這么神奇,那么具體怎么用呢?MST 只是一個(gè)狀態(tài)容器,同時(shí)包含了可變數(shù)據(jù)和不可變數(shù)據(jù)。你可以用 MST 直接搭配 React 使用。可以 MST + Mobx + React 配合著用,還可以 MST + Redux + React 混搭著用。

MST 比較新,業(yè)內(nèi)的實(shí)踐非常少,如果不是急需,現(xiàn)在還可以先觀望一下。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/83894.html

相關(guān)文章

  • 【譯】Redux 還是 Mobx,讓我來解決你的困惑!

    摘要:我現(xiàn)在寫的這些是為了解決和這兩個(gè)狀態(tài)管理庫之間的困惑。這甚至是危險(xiǎn)的,因?yàn)檫@部分人將無法體驗(yàn)和這些庫所要解決的問題。這肯定是要第一時(shí)間解決的問題。函數(shù)式編程是不斷上升的范式,但對(duì)于大部分開發(fā)者來說是新奇的。規(guī)模持續(xù)增長的應(yīng) 原文地址:Redux or MobX: An attempt to dissolve the Confusion 原文作者:rwieruch 我在去年大量的使用...

    txgcwm 評(píng)論0 收藏0
  • 比Redux更容易上手的狀態(tài)管理

    摘要:前言當(dāng)項(xiàng)目越發(fā)復(fù)雜時(shí),我們發(fā)現(xiàn)僅僅是提升狀態(tài)已經(jīng)無法適應(yīng)如此復(fù)雜的狀態(tài)管理了,程序狀態(tài)變得比較難同步,操作,到處是回調(diào),發(fā)布,訂閱,這意味著我們需要更好的狀態(tài)管理方式,于是就引入了狀態(tài)管理庫,如,,,等。 前言 當(dāng)項(xiàng)目越發(fā)復(fù)雜時(shí),我們發(fā)現(xiàn)僅僅是提升狀態(tài)已經(jīng)無法適應(yīng)如此復(fù)雜的狀態(tài)管理了,程序狀態(tài)變得比較難同步,操作,到處是回調(diào),發(fā)布,訂閱,這意味著我們需要更好的狀態(tài)管理方式,于是就引入了...

    CNZPH 評(píng)論0 收藏0
  • 個(gè)人愚見:Redux 和 Mobx 區(qū)別

    摘要:一關(guān)于狀態(tài)管理它們都有統(tǒng)一維護(hù)管理應(yīng)用狀態(tài)的能力某一狀態(tài)只有一個(gè)可信數(shù)據(jù)來源通常命名為,指狀態(tài)容器操作更新狀態(tài)方式統(tǒng)一,并且可控通常以方式提供更新狀態(tài)的途徑支持將與組件連接,如,通常使用狀態(tài)管理庫后,我們將組件從業(yè)務(wù)上劃分為兩類容器組件 一. 關(guān)于狀態(tài)管理 它們都有統(tǒng)一維護(hù)管理應(yīng)用狀態(tài)的能力; 某一狀態(tài)只有一個(gè)可信數(shù)據(jù)來源(通常命名為store,指狀態(tài)容器); 操作更新狀態(tài)方式統(tǒng)一,并...

    dcr309duan 評(píng)論0 收藏0
  • mobx——rudex的簡單替代品

    摘要:是一個(gè)的簡單可擴(kuò)展的狀態(tài)管理庫。它的副作用是自動(dòng)更新。該函數(shù)返回一個(gè)值,當(dāng)返回值為的時(shí)候,才會(huì)繼續(xù)觸發(fā)第一個(gè)函數(shù)。當(dāng)返回值為時(shí),不再繼續(xù)監(jiān)聽。包含一個(gè),該值用來區(qū)分執(zhí)行事件的類型。 mobx 能干什么 使用 react 寫小型應(yīng)用,數(shù)據(jù)、業(yè)務(wù)邏輯和視圖的模塊劃分不是很細(xì)是沒有問題的。在這個(gè)階段,引入任何狀態(tài)管理庫,都算是奢侈的。但是隨著頁面邏輯的復(fù)雜度提升,在中大型應(yīng)用中,數(shù)據(jù)、業(yè)務(wù)邏...

    DevWiki 評(píng)論0 收藏0
  • React + MobX 入門及實(shí)例(一)

    摘要:前言現(xiàn)在最熱門的前端框架,毫無疑問是。對(duì)于小型應(yīng)用,引入狀態(tài)管理庫是奢侈的。但對(duì)于復(fù)雜的中大型應(yīng)用,引入狀態(tài)管理庫是必要的。現(xiàn)在熱門的狀態(tài)管理解決方案,相繼進(jìn)入開發(fā)者的視野。獲得計(jì)算得到的新并返回。 前言 現(xiàn)在最熱門的前端框架,毫無疑問是React。 React是一個(gè)狀態(tài)機(jī),由開始的初始狀態(tài),通過與用戶的互動(dòng),導(dǎo)致狀態(tài)變化,從而重新渲染UI。 對(duì)于小型應(yīng)用,引入狀態(tài)管理庫是奢侈的。 但...

    simon_chen 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<