成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

MobX

Alliot / 590人閱讀

摘要:建議將它們用于修改可觀察量或具有副作用的任何函數(shù)中。這意味著在一些定時(shí)器或者網(wǎng)絡(luò)請(qǐng)求,異步處理的情況下,它們的回調(diào)函數(shù)無(wú)法對(duì)狀態(tài)做成改變。這些回調(diào)函數(shù)都應(yīng)該有包裹,如果例子里面的一樣。

1. 介紹 1.1. 原理

React的render是 狀態(tài) 轉(zhuǎn)化為樹(shù)狀結(jié)構(gòu)的渲染組件的方法
而MobX提供了一種存儲(chǔ),更新 狀態(tài) 的方法
React 和 MobX都在優(yōu)化著軟件開(kāi)發(fā)中相同的問(wèn)題。
React 使用的方法是讓虛擬DOM來(lái)減少繁瑣而沉重的DOM變化。
而MobX則通過(guò)一個(gè)虛擬的狀態(tài)依賴圖表來(lái)讓react組件和應(yīng)用狀態(tài)同步化來(lái)減少不必要的狀態(tài)導(dǎo)致組件更新

1.2. 安裝

MobX:

npm install mobx --save

React bindings:

npm install mobx-react --save
1.3. 要點(diǎn)

MobX看起來(lái)很復(fù)雜的樣子,其實(shí)是用它只需要三步

定義你的狀態(tài),讓它們成為觀察者(observable)
存儲(chǔ)狀態(tài)(Store state)可以是任何的數(shù)據(jù)結(jié)構(gòu),隨你定義為:對(duì)象,數(shù)組,類,循環(huán)結(jié)構(gòu),引用都沒(méi)所謂。但需要記住一點(diǎn),就是:隨著時(shí)間的變化,用MobX 去把它們定義成觀察者(observable)

import {observable} from "mobx"
let appState = observable({
    timer: 0
})

我們不需要讓appState去觀察什么。你現(xiàn)在就能創(chuàng)建視圖(view),每當(dāng)appState的相關(guān)數(shù)據(jù)發(fā)生變化的時(shí)候,就會(huì)自動(dòng)更新。MobX會(huì)采用最優(yōu)的方式去更新你的視圖。以下有一個(gè)例子來(lái)說(shuō)明如何使用,其中使用了ES6/ES7的語(yǔ)法(當(dāng)然MobX也是支持ES5),代碼中@的意義

import {observer} from "mobx-react";
@observer
class TimerView extends React.Component {
    render() {
        return ();
    }
    onReset () {
        //appState.resetTimer會(huì)在下一節(jié)完成
        this.props.appState.resetTimer();
    }
};
React.render(, document.body);

修改狀態(tài)
第三節(jié)要說(shuō)的是修改狀態(tài)。MobX和其他框架不同,它不會(huì)要求你去做什么事情,它只是幫助你去做簡(jiǎn)單的事情

appState.resetTimer = action(function reset() {
    appState.timer = 0;
});
setInterval(action(function tick() {
    appState.timer += 1;
}), 1000);

其中action包裝用法只能在strict模式下使用,請(qǐng)記得在你的javascript文件頭寫(xiě)上:"use strict"。

2. API

從上面的例子可以看到,MobX的API其實(shí)不多:observable, computed, reactions, actions

2.1. observable(value)

其中的value可以是JS原定的數(shù)據(jù)結(jié)構(gòu),引用,對(duì)象,數(shù)組,ES6的map

如果value是一個(gè)map的話,則需要使用一個(gè)調(diào)節(jié)器(modifier)asMap來(lái)使用。這時(shí)候會(huì)返回一個(gè)Observable Map

如果是一個(gè)數(shù)組,返回Observable Array

如果是一個(gè)沒(méi)有屬性的對(duì)象,則返回一個(gè)Observable Object

如果是一個(gè)有屬性的對(duì)象,JS原有的數(shù)據(jù)結(jié)構(gòu),函數(shù)等,返回一個(gè) Boxed Observable。MobX不會(huì)自動(dòng)讓一個(gè)有屬性的對(duì)象成為觀察者。這是這個(gè)有屬性的對(duì)象的構(gòu)造函數(shù)應(yīng)該做的事情,你可以使用extendObservable在它的構(gòu)造函數(shù)里面,或者在它的類使用@observable去定義。

以下是一些例子:

const map = observable(asMap({ key: "value"}));
map.set("key", "new value");

const list = observable([1, 2, 4]);
list[2] = 3;

const person = observable({
    firstName: "Clive Staples",
    lastName: "Lewis"
});
person.firstName = "C.S.";

const temperature = observable(20);
temperature.set(25);
2.2. @observable
import {observable} from "mobx";
class OrderLine {
    @observable price:number = 0;
    @observable amount:number = 1;
    constructor(price) {
        this.price = price;
    }
    //這里在下一節(jié)會(huì)說(shuō)到
    @computed get total() {
        return this.price * this.amount;
    }
}
const line = new OrderLine();
console.log("price" in line); // true
//hasOwnProperty:判斷一個(gè)對(duì)象是否有你給出名稱的屬性或?qū)ο蟆P枰⒁?,此方法無(wú)法檢查該對(duì)象的原型鏈中是否具有該屬性
console.log(line.hasOwnProperty("price")); //false

如果你的環(huán)境不支持ES6/7的語(yǔ)法的話,其實(shí)@observable key = value; 只是extendObservable(this, { key: value })的語(yǔ)法糖。因此在ES5環(huán)境下你也能使用

2.3. (@)computed

Computed values 就像一個(gè)算術(shù)公式一樣去從現(xiàn)有的狀態(tài)或其他值去計(jì)算出需要的值。計(jì)算的耗費(fèi)是不可低估的。Computed盡可能幫你減少其中的耗費(fèi)。它們是高度優(yōu)化的,請(qǐng)把它用在可能用到的地方。

不要混淆下一節(jié)說(shuō)到的autorun。雖然他們都是被動(dòng)調(diào)用的表達(dá)式。但是……
Computed使用情況:如果你需要產(chǎn)生一個(gè)有觀察者(observers)參數(shù)計(jì)算的新的值的時(shí)候
autorun使用情況:你不想產(chǎn)生一個(gè)新的值就想達(dá)到一個(gè)新的效果/功能。就像是打log或者進(jìn)行網(wǎng)絡(luò)請(qǐng)求
Computed values是自動(dòng)幫你從你的狀態(tài)(state)值和其他計(jì)算輔助值來(lái)計(jì)算的。MobX做了很多的優(yōu)化。當(dāng)參與計(jì)算的值沒(méi)有發(fā)生改變,Computed是不會(huì)重新運(yùn)行。如果參與計(jì)算的值沒(méi)有被使用,Computed values是暫停的。

如果Computed values不再是觀察者(observed),那么在UI上也會(huì)把它除掉,MobX能自動(dòng)做垃圾回收。autorun則需要你自己手動(dòng)去處理。如果參與計(jì)算的值不再被使用,是不會(huì)緩存Computed的,所以重新計(jì)算是需要的。這個(gè)是最理想的默認(rèn)情況。如果你想保留,可以了解一下keepalive和observe。

例子1: 在2.2的例子。@computed get

例子2: @computed set

class Foo {
    @observable length: 2,
    @computed get squared() {
        return this.length * this.length;
    }
    set squared(value) { //this is automatically an action, no annotation necessary
        this.length = Math.sqrt(value);
    }
}

需要注意的是:setter并非用于直接改變參數(shù)計(jì)算的值,如例子中的length。而是作為一個(gè)逆推導(dǎo)。

2.4. Autorun

Autorun是用在一些你想要產(chǎn)生一個(gè)不用觀察者參與的被動(dòng)調(diào)用函數(shù)里面。當(dāng)autorun被使用的時(shí)候,一旦依賴項(xiàng)發(fā)生變化,autorun提供的函數(shù)就會(huì)被執(zhí)行。與之相反的是,computed提供的函數(shù)只會(huì)在他有自己的觀察員(observers)的時(shí)候才會(huì)評(píng)估是否重新執(zhí)行,否則它的值被認(rèn)為是無(wú)用的。

根據(jù)這些經(jīng)驗(yàn):如果你需要一個(gè)自動(dòng)運(yùn)行但卻不會(huì)產(chǎn)生任何新的值的結(jié)果的函數(shù),那么請(qǐng)使用Autorun。其他情況請(qǐng)使用computed。Autorun只是作用于如果達(dá)到某個(gè)效果或者功能,而不是計(jì)算某些值。如果有一個(gè)字符串作為第一個(gè)參數(shù)存入Autorun,那么它將成為一個(gè)調(diào)試名稱。

var numbers = observable([1,2,3]);
var sum = computed(() => numbers.reduce((a, b) => a + b, 0));

var disposer = autorun(() => console.log(sum.get()));
// prints "6"
numbers.push(4);
// prints "10"
2.5. @observer

observer 函數(shù)/修飾器用于react組件。通過(guò)mobx-react依賴包來(lái)提供。它通過(guò)mobx.autorun來(lái)包裝了組件的render函數(shù),以確保組件的render函數(shù)在任何數(shù)據(jù)的更改是強(qiáng)制重新渲染

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 }  )
    }
});
React.render(, document.body);

tips: 如果還有其他的decorators一起或者高階組件的存在,請(qǐng)確保observer為最內(nèi)層(優(yōu)先應(yīng)用)的修飾器。否則它可能無(wú)法工作。如果你只在ES5的環(huán)境下工作:其實(shí)observer不過(guò)是observer(class Timer ... { }) 的語(yǔ)法糖。

難點(diǎn)—組件中相關(guān)值的引用:
MobX能做的事情很多,但是它卻不能把原始的值變成觀察者(盡管可以通過(guò)包裹這個(gè)值來(lái)返回一個(gè)boxed observables的對(duì)象)。所以觀察者不是這個(gè)原始的值,而是返回后的對(duì)象的屬性值。修改一個(gè)剛才的例子:

React.render(, document.body)

這時(shí)候程序并不會(huì)工作了。傳入組件的只是timerData里面secondsPassed的當(dāng)前值。在組件里面,它是不可變的。

把你的組件內(nèi)部狀態(tài)變成可觀察的
和普通的類一樣,你可以在你的組件使用@observable修飾器。這意味著你的組件擁有了一個(gè)內(nèi)部state,而且它不需要使用react內(nèi)部提供的繁瑣的setState機(jī)制。這個(gè)內(nèi)部state能調(diào)起render函數(shù),但是卻不能準(zhǔn)確調(diào)起React的生命周期函數(shù),例如:componentShouldUpdate / componentWillUpdate。如果你想要這些,最好使用react提供的API來(lái)創(chuàng)建state。當(dāng)然也可以這樣寫(xiě)

import {observer} from "mobx-react"
import {observable} from "mobx"
@observer class Timer extends React.Component {
    @observable secondsPassed = 0
    componentWillMount() {
        setInterval(() => {
            this.secondsPassed++
        }, 1000)
    }
    render() {
        return (Seconds passed: { this.secondsPassed }  )
    }
})
React.render(, document.body)

連接observer和stores
mobx-react提供了Provider組件讓你可以把傳遞下來(lái)的stores作用在react提供的上下文機(jī)制。通過(guò)連接這些stores和observer,這些observer會(huì)成為組件的屬性來(lái)使用。

const colors = observable({
   foreground: "#000",
   background: "#fff"
});
const App = () =>
  
     
  ;
const Button = observer(["colors"], ({ colors, label, onClick }) =>
  

componentWillReact
React 的組件總是從新的堆棧去渲染。因此讓它它很難判斷一個(gè)組件是否需要重新渲染。在mobx-react里面,你可以使用重新定義的生命周期componentWillReact。它只會(huì)在觀察者發(fā)生變化的時(shí)候才重新渲染。

import {observer} from "mobx-react";
@observer class TodoView extends React.Component {
    componentWillReact() {
        console.log("I will re-render, since the todo has changed!");
    }
    render() {
        return 
this.props.todo.title
; } }

componentWillReact沒(méi)有任何參數(shù),而且不會(huì)在render初始化之前執(zhí)行(componentWillMount的區(qū)別)。而當(dāng)接收新的屬性或者setState之后,它會(huì)被調(diào)用。

2.6. action

任何應(yīng)用程序都有操作(action)。action是任何改變狀態(tài)的事物。使用MobX,您可以通過(guò)標(biāo)記它們?cè)谀拇a中顯式地顯示您的操作(action)。它會(huì)更好的幫助你組織你的代碼。建議將它們用于修改可觀察量或具有副作用的任何函數(shù)中。
需要注意的是:action是用在strict mode 中的

action(fn)
action(name, fn)
@action classMethod() {}
@action(name) classMethod () {}
@action boundClassMethod = (args) => { body }
@action(name) boundClassMethod = (args) => { body }
@action.bound classMethod() {}
@action.bound(function() {})
@action createRandomContact() {
    this.pendingRequestCount++;
    superagent
         .get("https://randomuser.me/api/")
         .set("Accept", "application/json")
         .end(action("createRandomContact-callback", (error, results) => {
                 if (error) console.error(error)
                 else {
                     const data = JSON.parse(results.text).results[0];
                     const contact = new Contact(this, data.dob, data.name, data.login.username, data.picture)
                     contact.addTag("random-user");
                     this.contacts.push(contact);
                     this.pendingRequestCount--;
                 }
        }
))}

action 僅僅作用于當(dāng)前運(yùn)行的函數(shù),而不能作用于當(dāng)前函數(shù)調(diào)用的函數(shù)。這意味著在一些定時(shí)器或者網(wǎng)絡(luò)請(qǐng)求,異步處理的情況下,它們的回調(diào)函數(shù)無(wú)法對(duì)狀態(tài)做成改變。這些回調(diào)函數(shù)都應(yīng)該有action包裹,如果例子里面的 createRandomContact-callback 一樣。但是,如果你使用了async / await的話,最好的方式應(yīng)該是使用 runInAction 來(lái)讓它變得更加簡(jiǎn)單

@action /*optional*/ updateDocument = async () => {
    const data = await fetchDataFromUrl();
    /* required in strict mode to be allowed to update state: */
    runInAction("update state after fetching data", () => {
        this.data.replace(data);
        this.isSaving = true;
    })
}

Bound actions
目前看到的actions都是遵循在javascript中綁定的正常規(guī)則,但是在MobX 3引入了action.bound來(lái)自動(dòng)綁定actions到目標(biāo)對(duì)象上。和action的使用不一樣,不需要一個(gè)名字參數(shù)。它的名稱始終基于綁定到屬性的操作上。需要注意的是,在箭頭函數(shù)上不要這樣使用,因?yàn)榧^函數(shù)已經(jīng)綁定了上下文,不能在重新更改上下文

class Ticker {
    @observable this.tick = 0

    @action.bound
    increment() {
        this.tick++ // "this" will always be correct
    }
}
const ticker = new Ticker()
setInterval(ticker.increment, 1000)
后記

啟動(dòng)例子項(xiàng)目:進(jìn)入

前端項(xiàng)目:npm install 或者 yarn install 打開(kāi)本地的8080端口

后端部分:進(jìn)入 back文件夾,執(zhí)行npm start 打開(kāi)本地的3000端口

作為對(duì)比:使用redux的例子:進(jìn)入

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/81421.html

相關(guān)文章

  • mobx學(xué)習(xí)總結(jié)

    摘要:原理分析的核心就是通過(guò)觀察某一個(gè)變量,當(dāng)該變量產(chǎn)生變化時(shí),對(duì)應(yīng)的內(nèi)的回調(diào)函數(shù)就會(huì)發(fā)生變化?;卣{(diào)函數(shù)若依賴外部環(huán)境,則無(wú)法進(jìn)行收集很好理解,的回調(diào)函數(shù)在預(yù)執(zhí)行的時(shí)候無(wú)法到達(dá)那一行代碼,所以收集不到。 Mobx解決的問(wèn)題 傳統(tǒng)React使用的數(shù)據(jù)管理庫(kù)為Redux。Redux要解決的問(wèn)題是統(tǒng)一數(shù)據(jù)流,數(shù)據(jù)流完全可控并可追蹤。要實(shí)現(xiàn)該目標(biāo),便需要進(jìn)行相關(guān)的約束。Redux由此引出了dispa...

    roundstones 評(píng)論0 收藏0
  • 【譯】Redux 還是 Mobx,讓我來(lái)解決你的困惑!

    摘要:我現(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 我在去年大量的使用...

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

    摘要:是一個(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í)行事件的類型。 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ù)邏...

    DevWiki 評(píng)論0 收藏0
  • React 狀態(tài)管理庫(kù): Mobx

    摘要:關(guān)心性能的情況下,需要手動(dòng)設(shè)置這時(shí)就需要引入狀態(tài)管理庫(kù)?,F(xiàn)在常用的狀態(tài)管理庫(kù)有和,本文會(huì)重點(diǎn)介紹,然后會(huì)將和進(jìn)行對(duì)比,最后展望下未來(lái)的狀態(tài)管理方面趨勢(shì)。如果在任何地方都修改可觀察數(shù)據(jù),將導(dǎo)致頁(yè)面狀態(tài)難以管理。 React 是一個(gè)專注于視圖層的庫(kù)。React 維護(hù)了狀態(tài)到視圖的映射關(guān)系,開(kāi)發(fā)者只需關(guān)心狀態(tài)即可,由 React 來(lái)操控視圖。 在小型應(yīng)用中,單獨(dú)使用 React 是沒(méi)什么問(wèn)題...

    liujs 評(píng)論0 收藏0
  • 【用故事解讀 MobX源碼(一)】 autorun

    摘要:隨后,執(zhí)行官給出一張當(dāng)張三存款發(fā)生變化之時(shí),此機(jī)構(gòu)的運(yùn)作時(shí)序圖的確,小機(jī)構(gòu)靠人力運(yùn)作,大機(jī)構(gòu)才靠制度運(yùn)轉(zhuǎn)。第一條語(yǔ)句創(chuàng)建觀察員第一條語(yǔ)句張三我們調(diào)用的時(shí)候,就創(chuàng)建了對(duì)象,對(duì)象的所有屬性都將被拷貝至一個(gè)克隆對(duì)象并將克隆對(duì)象轉(zhuǎn)變成可觀察的。 ================前言=================== 初衷:網(wǎng)上已有很多關(guān)于 MobX 源碼解讀的文章,但大多閱讀成本甚高。...

    qieangel2013 評(píng)論0 收藏0
  • 我為什么從Redux遷移到了Mobx

    摘要:需要注意的是,在中,需要把數(shù)據(jù)聲明為。同時(shí)還提供了運(yùn)行時(shí)的類型安全檢查。在利用了,使異步操作可以在一個(gè)函數(shù)內(nèi)完成并且可以被追蹤。例如在中,數(shù)組并不是一個(gè),而是一個(gè)類的對(duì)象,這是為了能監(jiān)聽(tīng)到數(shù)據(jù)下標(biāo)的賦值。 Redux是一個(gè)數(shù)據(jù)管理層,被廣泛用于管理復(fù)雜應(yīng)用的數(shù)據(jù)。但是實(shí)際使用中,Redux的表現(xiàn)差強(qiáng)人意,可以說(shuō)是不好用。而同時(shí),社區(qū)也出現(xiàn)了一些數(shù)據(jù)管理的方案,Mobx就是其中之一。 R...

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

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

0條評(píng)論

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