中文字幕日韩精品一区二区免费_精品一区二区三区国产精品无卡在_国精品无码专区一区二区三区_国产αv三级中文在线

使用RxJS管理React應(yīng)用狀態(tài)的方法-創(chuàng)新互聯(lián)

這篇文章主要介紹了使用RxJS管理React應(yīng)用狀態(tài)的方法,具有一定借鑒價(jià)值,需要的朋友可以參考下。希望大家閱讀完這篇文章后大有收獲。下面讓小編帶著大家一起了解一下。

10年積累的網(wǎng)站建設(shè)、做網(wǎng)站經(jīng)驗(yàn),可以快速應(yīng)對(duì)客戶對(duì)網(wǎng)站的新想法和需求。提供各種問(wèn)題對(duì)應(yīng)的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡(luò)服務(wù)。我雖然不認(rèn)識(shí)你,你也不認(rèn)識(shí)我。但先做網(wǎng)站設(shè)計(jì)后付款的網(wǎng)站建設(shè)流程,更有塔城免費(fèi)網(wǎng)站建設(shè)讓你可以放心的選擇與我們合作。

隨著前端應(yīng)用的復(fù)雜度越來(lái)越高,如何管理應(yīng)用的數(shù)據(jù)已經(jīng)是一個(gè)不可回避的問(wèn)題。當(dāng)你面對(duì)的是業(yè)務(wù)場(chǎng)景復(fù)雜、需求變動(dòng)頻繁、各種應(yīng)用數(shù)據(jù)互相關(guān)聯(lián)依賴的大型前端應(yīng)用時(shí),你會(huì)如何去管理應(yīng)用的狀態(tài)數(shù)據(jù)呢?

我們認(rèn)為應(yīng)用的數(shù)據(jù)大體上可以分為四類:

  • 事件:瞬間產(chǎn)生的數(shù)據(jù),數(shù)據(jù)被消費(fèi)后立即銷毀,不存儲(chǔ)。
  • 異步:異步獲取的數(shù)據(jù);類似于事件,是瞬間數(shù)據(jù),不存儲(chǔ)。
  • 狀態(tài):隨著時(shí)間空間變化的數(shù)據(jù),始終會(huì)存儲(chǔ)一個(gè)當(dāng)前值/最新值。
  • 常量:固定不變的數(shù)據(jù)。

RxJS天生就適合編寫異步和基于事件的程序,那么狀態(tài)數(shù)據(jù)用什么去管理呢?還是用RxJS嗎? 合不合適呢?

我們?nèi)フ{(diào)研和學(xué)習(xí)了前端社區(qū)已有的優(yōu)秀的狀態(tài)管理解決方案,也從一些大牛分享的關(guān)于用RxJS設(shè)計(jì)數(shù)據(jù)層的構(gòu)想和實(shí)踐中得到了啟發(fā):

  1. 使用RxJS完全可以實(shí)現(xiàn)諸如Redux,Mobx等管理狀態(tài)數(shù)據(jù)的功能。
  2. 應(yīng)用的數(shù)據(jù)不是只有狀態(tài)的,還有事件、異步、常量等等。如果整個(gè)應(yīng)用都由observable來(lái)表達(dá),則可以借助RxJS基于序列且可響應(yīng)的的特性,以流的方式自由地拼接和組合各種類型的數(shù)據(jù),能夠更優(yōu)雅更高效地抽象出可復(fù)用可擴(kuò)展的業(yè)務(wù)模型。

出于以上兩點(diǎn)原因,最終決定基于RxJS來(lái)設(shè)計(jì)一套管理應(yīng)用的狀態(tài)的解決方案。

原理介紹

對(duì)于狀態(tài)的定義,通常認(rèn)為狀態(tài)需要滿足以下3個(gè)條件:

  1. 是一個(gè)具有多個(gè)值的集合。
  2. 能夠通過(guò)event或者action對(duì)值進(jìn)行轉(zhuǎn)換,從而得到新的值。
  3. 有“當(dāng)前值”的概念,對(duì)外一般只暴露當(dāng)前值,即最新值。

那么,RxJS適合用來(lái)管理狀態(tài)數(shù)據(jù)嗎?答案是肯定的!

首先,因?yàn)?code>Observable本身就是多個(gè)值的推送集合,所以第一個(gè)條件是滿足的!

其次,我們可以實(shí)現(xiàn)一個(gè)使用dispatch action模式來(lái)推送數(shù)據(jù)的observable來(lái)滿足第二個(gè)條件!

眾所周知,RxJS中的observable可以分為兩種類型:

cold observable: 推送值的生產(chǎn)者(producer)來(lái)自observable內(nèi)部。

  • 將會(huì)推送幾個(gè)值以及推送什么樣的值已在observable創(chuàng)建時(shí)被定義下來(lái),不可改變。
  • producer與觀察者(observer) 是一對(duì)一的關(guān)系,即是單播的。
  • 每當(dāng)有observer訂閱時(shí),producer都會(huì)把預(yù)先定義好的若干個(gè)值依次推送給observer

hot observable: 推送值的producer來(lái)自observable外部。

  • 將會(huì)推送幾個(gè)值、推送什么樣的值以及何時(shí)推送在創(chuàng)建時(shí)都是未知的。
  • producerobserver是一對(duì)多的關(guān)系,即是多播的。
  • 每當(dāng)有observer訂閱時(shí),會(huì)將observer注冊(cè)到觀察者列表中,類似于其他庫(kù)或語(yǔ)言中的addListener的工作方式。
  • 當(dāng)外部的producer被觸發(fā)或執(zhí)行時(shí),會(huì)將值同時(shí)推送給所有的observer;也就是說(shuō),所有的observer共享了hot observable推送的值。

RxJS提供的BehaviorSubject就是一種特殊的hot observable,它向外暴露了推送數(shù)據(jù)的接口next函數(shù);并且有“當(dāng)前值”的概念,它保存了發(fā)送給observer的最新值,當(dāng)有新的觀察者訂閱時(shí),會(huì)立即從BehaviorSubject那接收到“當(dāng)前值”。

那么這說(shuō)明使用BehaviorSubject來(lái)更新?tīng)顟B(tài)并保存狀態(tài)的當(dāng)前值是可行的,第三個(gè)條件也滿足了。

簡(jiǎn)單實(shí)現(xiàn)

請(qǐng)看以下的代碼:

import { BehaviorSubject } from 'rxjs';

// 數(shù)據(jù)推送的生產(chǎn)者
class StateMachine {
  constructor(subject, value) {
    this.subject = subject;
    this.value = value;
  }

  producer(action) {
    let oldValue = this.value;
    let newValue;
    switch (action.type) {
      case 'plus':
        newValue = ++oldValue;
        this.value = newValue;
        this.subject.next(newValue);
        break;
      case 'toDouble':
        newValue = oldValue * 2;
        this.value = newValue;
        this.subject.next(newValue);
        break;
    }
  }
}

const value = 1;  // 狀態(tài)的初始值
const count$ = new BehaviorSubject(value);
const stateMachine = new StateMachine(count$, value);

// 派遣action
function dispatch(action) {
  stateMachine.producer(action);
}

count$.subscribe(val => {
  console.log(val);
});

setTimeout(() => {
  dispatch({
    type: "plus"
  });
}, 1000);

setTimeout(() => {
  dispatch({
    type: "toDouble"
  });
}, 2000);

執(zhí)行代碼控制臺(tái)會(huì)打印出三個(gè)值:

Console

 1
 2
 4

上面的代碼簡(jiǎn)單實(shí)現(xiàn)了一個(gè)簡(jiǎn)單管理狀態(tài)的例子:

  • 狀態(tài)的初始值: 1
  • 執(zhí)行plus之后的狀態(tài)值: 2
  • 執(zhí)行toDouble之后的狀態(tài)值: 4

實(shí)現(xiàn)方法挺簡(jiǎn)單的,就是使用BehaviorSubject來(lái)表達(dá)狀態(tài)的當(dāng)前值:

  • 第一步,通過(guò)調(diào)用dispatch函數(shù)使producer函數(shù)執(zhí)行
  • 第二部,producer函數(shù)在內(nèi)部調(diào)用了BehaviorSubjectnext函數(shù),推送了新數(shù)據(jù),BehaviorSubject的當(dāng)前值更新了,也就是狀態(tài)更新了。

不過(guò)寫起來(lái)略微繁瑣,我們對(duì)其進(jìn)行了封裝,優(yōu)化后寫法見(jiàn)下文。

使用操作符來(lái)創(chuàng)建狀態(tài)數(shù)據(jù)

我們自定義了一個(gè)操作符state用來(lái)創(chuàng)建一個(gè)能夠通過(guò)dispatch action模式推送新數(shù)據(jù)的BehaviorSubject,我們稱她為stateObservable。

const count$ = state({
  // 狀態(tài)的唯一標(biāo)識(shí)名稱
  name: "count",
    
  // 狀態(tài)的默認(rèn)值
  defaultValue: 1,
    
  // 數(shù)據(jù)推送的生產(chǎn)者函數(shù)
  producer(next, value, action) {
    switch (action.type) {
      case "plus":
        next(value + 1);
        break;
      case "toDouble":
        next(value * 2);
        break;
    }
  }
});

更新?tīng)顟B(tài)

在你想要的任意位置使用函數(shù)dispatch派遣action即可更新?tīng)顟B(tài)!

dispatch("count", {
  type: "plus"
})

異步數(shù)據(jù)

RxJS的一大優(yōu)勢(shì)就在于能夠統(tǒng)一同步和異步,使用observable處理數(shù)據(jù)你不需要關(guān)注同步還是異步。

下面的例子我們使用操作符frompromise轉(zhuǎn)換為observable。

指定observable作為狀態(tài)的初始值(首次推送數(shù)據(jù))
const todos$ = state({
  name: "todos",
    
  // `observable`推送的數(shù)據(jù)將作為狀態(tài)的初始值
  initial: from(getAsyncData())
    
  //...
  
});
producer推送observable
const todos$ = state({
  name: "todos",
    
  defaultValue: []
    
  // 數(shù)據(jù)推送的生產(chǎn)者函數(shù)
  producer(next, value, action) {
    switch (action.type) {
      case "getAsyncData":
        next(
          from(getAsyncData())
        );
        break;
    }
  }
});

執(zhí)行getAsyncData之后,from(getAsyncData())的推送數(shù)據(jù)將成為狀態(tài)的最新值。

衍生狀態(tài)

由于狀態(tài)todos$是一個(gè)observable,所以可以很自然地使用RxJS操作符轉(zhuǎn)換得到另一個(gè)新的observable。并且這個(gè)observable的推送來(lái)自todos$;也就是說(shuō)只要todos$推送新數(shù)據(jù),它也會(huì)推送;效果類似于Vue的計(jì)算屬性。

// 未完成任務(wù)數(shù)量
const undoneCount$ = todos$.pipe(
  map(todos => {
    let _conut = 0;
    todos.forEach(item => {
      if (!item.check) ++_conut;
    });
    return _conut;
  })
);

React視圖渲染

我們可能會(huì)在組件的生命周期內(nèi)訂閱observable得到數(shù)據(jù)渲染視圖。

class Todos extends React.Component {
  componentWillMount() {
    todos$.subscribe(data => {
      this.setState({
        todos: data
      });
    });
  }
}

我們可以再優(yōu)化下,利用高階組件封裝一個(gè)裝飾器函數(shù)@subscription,顧名思義,就是為React組件訂閱observable以響應(yīng)推送數(shù)據(jù)的變化;它會(huì)將observable推送的數(shù)據(jù)轉(zhuǎn)換為React組件的props

@subscription({
  todos: todos$
})
class TodoList extends React.Component {
  render() {
    return (
      <p className="todolist">
        <h2 className="header">任務(wù)列表</h2>
        {this.props.todos.map((item, n) => {
          return <TodoItem item={item} key={item.desc} />;
        })}
      </p>
    );
  }
}

總結(jié)

使用RxJS越久,越令人受益匪淺。

  • 因?yàn)樗?code>observable序列提供了較高層次的抽象,并且是觀察者模式,可以盡可能地減少各組件各模塊之間的耦合度,大大減輕了定位BUG和重構(gòu)的負(fù)擔(dān)。
  • 因?yàn)槭腔?code>observable序列來(lái)編寫代碼的,所以遇到復(fù)雜的業(yè)務(wù)場(chǎng)景,總能按照一定的順序使用observable描述出來(lái),代碼的可讀性很強(qiáng)。并且當(dāng)需求變動(dòng)時(shí),我可能只需要調(diào)整下observable的順序,或者加個(gè)操作符就行了。再也不必因?yàn)橐粋€(gè)復(fù)雜的業(yè)務(wù)流程改動(dòng)了,需要去改好幾個(gè)地方的代碼(而且還容易改出BUG,笑~)。

所以,以上基于RxJS的狀態(tài)管理方案,對(duì)我們來(lái)說(shuō)是一個(gè)必需品,因?yàn)槲覀冺?xiàng)目中大量使用了RxJS,如果狀態(tài)數(shù)據(jù)也是observable,對(duì)我們抽象可復(fù)用可擴(kuò)展的業(yè)務(wù)模型是一個(gè)非常大的助力。當(dāng)然了,如果你的項(xiàng)目中沒(méi)有使用RxJS,也許ReduxMobx是更合適的選擇。

這套基于RxJS的狀態(tài)管理方案,我們已經(jīng)用于開(kāi)發(fā)公司的商用項(xiàng)目,反饋還不錯(cuò)。所以我們決定把這套方案整理成一個(gè)js lib,取名為:Floway,并在github上開(kāi)源:

  • github源碼:https://github.com/shayeLee/floway
  • 使用文檔:https://shayelee.github.io/floway

感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享使用RxJS管理React應(yīng)用狀態(tài)的方法內(nèi)容對(duì)大家有幫助,同時(shí)也希望大家多多支持創(chuàng)新互聯(lián),關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,遇到問(wèn)題就找創(chuàng)新互聯(lián),詳細(xì)的解決方法等著你來(lái)學(xué)習(xí)!

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無(wú)理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。

網(wǎng)站名稱:使用RxJS管理React應(yīng)用狀態(tài)的方法-創(chuàng)新互聯(lián)
URL地址:http://www.rwnh.cn/article36/dgsssg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站制作、App開(kāi)發(fā)、全網(wǎng)營(yíng)銷推廣、網(wǎng)站設(shè)計(jì)公司、定制開(kāi)發(fā)、網(wǎng)站制作

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都app開(kāi)發(fā)公司
时尚| 遂川县| 黎城县| 建始县| 平原县| 锡林郭勒盟| 新兴县| 安平县| 兴化市| 隆回县| 仁布县| 宁武县| 全州县| 辽阳县| 平潭县| 萨迦县| 康保县| 衡水市| 汤阴县| 临清市| 彰化市| 北碚区| 武胜县| 石棉县| 绿春县| 仪陇县| 洛南县| 崇阳县| 南安市| 永平县| 松原市| 永登县| 彭阳县| 涟源市| 东莞市| 罗城| 齐河县| 延庆县| 恭城| 河东区| 商河县|