<font id="zqva1"></font>
<rt id="zqva1"></rt>
  • <tt id="zqva1"></tt>
    <cite id="zqva1"></cite>

    <cite id="zqva1"><noscript id="zqva1"></noscript></cite>
      <rp id="zqva1"><meter id="zqva1"></meter></rp>

        <cite id="zqva1"></cite>
          <b id="zqva1"></b>
          <rp id="zqva1"></rp>
          <cite id="zqva1"></cite>

          <rt id="zqva1"></rt>

        1. <rp id="zqva1"></rp>

          react關于 Redux與flux的比較學習

          時間:?2017-12-05閱讀:?1707標簽:?redux

          1、flux框架介紹

          1.1 flux四大元素:

          • Dispatcher:根據注冊派發動作(action)
          • Store: 存儲數據,處理數據
          • Action:用于驅動Dispatcher
          • View: 用戶界面視圖
          Dispatcher

          是全局唯一的Dispatcher對象,關系網的中心

          // AppDispatcher.js
          // 完成聲明即可,后續無需改動
          // 注冊action等事件主要在store中被調用完成
          import {Dispatcher} from 'flux';
          export default new Dispatcher ();
          
          Store

          注冊(register):把當前store注冊到Dispatcher下,加入dispatcher關系網
          通過emit廣播、on掛載事件
          store需要注冊到全局唯一的Dispatcher上才有效
          flux核心部分:當register函數把一個回調函數注冊到Dispatcher后,所有派發給Dispatcher的action對象,都會傳遞到這個回調函數中

          const counterValues = {
              'First': 0,
              'Second': 10,
              'Third': 30
          }
          
          // 聲明、生成store對象
          const CounterStore = object.assign({}, EventEmitter.prototype, {
              getCounterValues: function() {
                  return counterValues;
              },
              emitChange: function(){
                  this.emit(CHANGE_EVENT);             // 廣播事件
              },
              addChangeListener: function(){
                  this.on(CHANGE_EVENT, callback);     // 掛載事件
              },
              removeChangeListener: fucntion(){
                  this.removeListener(CHANGE_EVENT, callback);      // 移除監聽
              }
          })
          
          
          // 把CounterStore注冊到全局唯一的Dispatcher上,register函數接受一個回調函數做參數
          //注冊token(控制權令牌)
          CounterStore.dispatchToken = AppDispathcer.register((action)=>{
              if(action.type === ActionTypes.INCREMENT){
                  // do increment
                  // 根據action對象,修改當前store中的counterValues變量
              } else if(action.type === ActionTypes.DECREMENT){
                  // do decrement 
                  // 根據action對象,修改當前store中的counterValues變量
              }
          })   
          

          使用waitFor()函數,通過dispatchToken的傳遞,實現同步調用,滿足多個store之間的相互依賴關系;
          常用于獲取store中的最新鮮的數據

          Action

          代表一個動作的純數據對象
          是js對象,且不自帶方法,用于驅動Dispatcher,來自用戶的請求
          Action并不包含數據處理邏輯,而是調用函數,來創建對應的action對象

          // ActionTypes.js
          export const INCREMENT = 'increment';
          export const DECREMENT = 'decrement';
          
          // action.js
          import * as ActionTypes form './ActionTypes.js';
          import AppDispatcher from './AppDispatcher.js'
          
          export const increment = (counterCaption) => {
              AppDispatcher.dispatch({
                  type: ActionTypes.INCREMENT,       // action對象類型
                  counterCaption:counterCaption      // 用于標識發出action的來源(即頁面元素)
              })
          }
          
          View

          用戶在界面中調用action

          // react組件中的事件
          onClickBtn() {
              // increment已經在對應的store中完成注冊,Dispactcher可識別
              Actions.increment(this, props.caption);
          }
          


          1.2 flux的擬人化描述

          Dispatcher:
          在十字路口中央指揮交通的交警,不會離開工作地點,是唯一的;
          當有人督促我派發(dispatch)一下action,我就要打電話給我的小協警了,叫他趕緊來把這個家伙的事處理一下;

          Store:
          注冊:協警把自己的電話號碼給了十字路口的交警并告訴他:“發生交通事故,就打這個電話找我,我來處理現場”;
          emit廣播事件:有人叫我去處理交通事故;
          on掛載事件:如果有人叫我去處理交通事故,我要給出的反應;

          view
          路上的車主,一旦和別人的車撞上了,我要發出一個action(下車跑去找交警告訴交警我的事故屬于哪種類型)讓交警知道我撞車了,不然他不會理我的;

          action
          車主督促交警,趕緊把我的action派發(dispatch)出去,讓協警快來處理一下;


          1.3 flux總結

          flux的目的:糾正MVC框架的無法禁絕view與model通信的缺點;

          flux的做法:store只有get方法,沒有set方法;因此view只能通過get獲取store狀態,不能修改狀態;如果想要修改store狀態,只能派發一個action給Dispatcher,由action中ActionTypes對應的store方法去修改store本身。

          flux的缺點

          • store之間的依賴:需要建立依賴,需要token
          • 可以但是很難進行服務器端渲染(尚不理解)
          • store替換后,無法保持原有存儲狀態(指在開發中,store邏輯的修改無法熱加載)


          2、Redux框架介紹

          2.1 Redux基本原則:

          • 繼承Flux基本原則:單向數據流
          • 唯一數據源
          • 保持狀態只讀
          • 只有純函數能改變數據
          1.唯一數據源

          Flux:利用Dispatcher的waitFor方法,保證多個store之間的依賴與更新順序 ==> 數據冗余、應用復雜
          Redux:所有state只保存在一個store中,整個應用只有一個store,狀態是一個樹形對象,每個組件使用狀態樹上的一部分數據

          2.保持狀態只讀

          狀態只可讀,不可直接修改
          渲染原則:UI = render(state) <===> 界面只根據State進行渲染
          與Flux相同,必須通過action對象才能修改store狀態

          3.只有純函數能改變數據

          純函數:指不依賴于且不改變它作用域之外的變量狀態的函數,也就是說函數的返回結果必須完全由傳入的參數決定

          reducer(state, action)
          reducer函數,接受兩個參數,第一個參數state是當前的狀態(最新的store.state),第二個參數action是接收到的action對象;reducer根據state與action的值產生并返回一個新的對象,返回的這一個對象用來組裝新狀態對象。

          2.2 Redux要素分析

          • Store:存儲數據
          • Reducer:根據Action+state替換state,而非直接修改
          • Aciton:定義Action對象
          • Component:調用action
          1.Store

          在Flux中,Dispatcher的作用:把action對象分發給不同的、已注冊的store;
          在redux中,只有一個store,是唯一的分發對象,因此將Dispatcher對象簡化為store對象中的一個函數dispatch。

          使用createStore創建整個應用唯一的store,并且暴露到全局;
          組件使用getOwnState函數用于從store中獲得狀態

          import {createStore} from 'redux';
          import reducer from './Reducer.js';
          
          const counterValues = {
              'First': 0,
              'Second': 10,
              'Third': 20
          }
          
          const store = createStore(reducer, initValues);   // reducer表示更新狀態的reducer,initValues是狀態的初始值
          
          export default store;
          
          
          2.Reducer

          reducer <===> redux與flux對state的操作差異
          flux:直接修改state的值
          redux:修改應用狀態,并不能直接修改狀態上的值,而是創建一個新的狀態對象返回給Redux,由Redux組裝新狀態對象。

          // Flux版本的action
          // Flux: 直接修改store狀態值
          CounterStore.dispatchToken = AppDispatcher.register( (action) => {
              if(action.type === AcitonTypes.INCREMENT) {
                  counterValues[action.counterCaption]++;
                  CounterStore.emitChange();
              } else if(action.type === AcitonTypes.DECREMENT){
                  counterValues[action.counterCaption]--;
                  CounterStore.emitChange();
              }
          })
          
          // Redux版本的action
          // 根據state與action的值產生并返回一個新的對象
          // 返回的這一個對象用來組裝新狀態對象。  
          function reducer (state,action) {
              const {counterCaption} = action;
          
              // 返回的對象是一個新的狀態樹
              // ... 擴展操作符
              // ...state表示擴展拆分state數據,去除了最頂層的樹結構,暴露二級節點
              // [counterCaption]: newData 則體現了redux狀態樹的設計
              // 使用組件的caption作為狀態樹的對應子數據字段
              switch (action.type) {
                  case ActionTypes.INCREMENT: 
                      return {...state, [counterCaption]: state[counterCaption] +1};
                  case ActionTypes.DECREMENT: 
                      return {...state, [counterCaption]: state[counterCaption] -1};
                  default: 
                      return state
              }
          }
          
          Action

          flux:Action構造函數不返回什么,而是把構造的動作函數立刻通過調用dispatcher函數派發出去

          // Flux之Action
          export const increment = (counterCaption) => {
              AppDispatcher.dispatch({
                  type: ActionTypes.INCREMENT,       // action對象類型
                  counterCaption:counterCaption      // 用于標識發出action的來源(即頁面元素)
              })
          }
          

          reudx:每個Action構造函數返回一個action對象 == > 返回一個對象,把處理對象的工作交給調用者

          // Redux之Action
          export const increment = (counterCaption) => {
              return {
                  type: ActionTypes.INCREMENT,       // action對象類型
                  counterCaption:counterCaption      // 用于標識發出action的來源(即頁面元素)
              })
          }
          
          
          
          
          Component

          用于聲明綁定派發action事件

          onIncrement() {
              // 通過dispatch派發aciton
              store.dispatch(Actions.increment(this.props.caption));
          }
          
          render() {
              const value = this.state.value;
              const {caption} = this.props;
              return (
                  <div>
                      <button onclick={this.onIncrement}>+</button>
                  </div>
              );
          }
          


          2.3 Redux的可改進之處

          1. 組件功能單一化

          當前組件具有兩個功能:1、派發Action,更新state樹;2、根據state與props渲染用戶界面
          為了使組件專注于單一功能 ===> 拆分組件(容器組件、展示組件)
          容器組件:外層組件,負責與store交互;
          展示組件:內層組件,負責渲染界面,無狀態;

          store 《====》 容器組件 ===(傳遞props)==》 展示組件 《====》 React界面

          2.context全局訪問對象

          理想目標
          單個應用最好只導入一次全局Store,在最頂層React組件的位置;
          為提高組件的復用性,其余組件應該避免直接導入Store;
          為了滿足以上原則而出現的缺點:在一個多層嵌套組件結構中,當只有最里層組件需要使用store,為了將sotre從最外層傳到最里層,必須在所有中間組件中使用props逐級傳遞state。

          Context:在樹狀組件中的所有組件都可訪問的一個共同對象,上下文環境
          當上級組件宣稱自己支持context,并且提供一個函數來返回代表context的對象,所有子孫組件可在宣稱(import)后通過this.context訪問到這個共同的環境變量。

          Provider類組件實現Context

          // Provider類組件實現Context
          
          import {PropTypes, Component} from 'react';
          
          class Provider extends Component {
              getChildContext() {
                  return {
                      store: this.props.store
                  };
              }
              
              render() {
                  // 渲染子組件   props.children代表子組件
                  return this.props.children;
              }
          }
          
          // 使Provider被React認可,成為一個Context提供者,必須指定childContextTypes屬性
          Provider.childContextTypes = {
              store: PropTypes.object
          };
          

          Provider提供Context,暴露到所有子組件中

          // Provider的實踐使用
          // index.js  應用入口文件
          import store from './Store.js'
          import Provider from './Provider.js';
          
          // ControlPanel是ReactDOM的頂層組件,現在被Provider組件包住后,Provider成為頂層組件
          // Provider內層包裹的所有
          ReactDOM.render (
              <Provider store={store}>
                  <ControlPanel />
              </Provider>,
              document.getElementById('root')
          )
          
          

          在子組件中使用Context

          // 第一步: 給組件類的contextTypes屬性賦值
          CounterContainer.contextTypes = {
              store: PropTypes.object
          }
          
          // 第二步:在構造函數中用上第二個參數context
          constructor(props, context) {
              // 寫法一:
              super(props, context);
              // 寫法二:
              super(...arguments);
          }
          
          
          // 第三步:通過this.context.store訪問store
          getOwnState() {
              return {
                  // [this.props.catption]用于獲取狀態樹中的某個二級狀態
                  value: this.context.store.getState()[this.props.catption]
              }
          }
          
          


          2.4 搭上大神的順風車—————— react-redux

          對于Redux的兩個改進在實現在實現上仍然具有一定的復雜性與機械性,因此已經有人創建了一個庫來幫我們完成這些工作(組件拆分與context)
          react-redux庫兩大功能:
          1、connect:連接容器組件與展示組件
          2、Provider:我們不再需要自己實現Provider來獲取context,可以使用庫提供的Provider

          connect

          包含了兩個函數中執行:connect與connect返回函數
          connect(mapStateToProps, mapDispatchToProps)的傳入參數是兩個映射函數,返回值是一個函數
          connect函數作用:
          1、向內傳遞state:把store上的狀態轉化為內層展示組件的props;
          2、向外轉發Action:把內層展示組件中的用戶動作轉化為派送給store的動作

          export default connect(mapStateToProps, mapDispatchToProps)(Counter);
          
          
          // mapStateToProps函數,向內傳遞state => props
          function mapStateToProps(state, ownProps) {
              return {
                  value: state[ownProps.caption]
              }
          }
          
          // mapDispatchToProps函數,向外轉發Action
          // ownProps屬性就是,直接傳遞給外層容器組件的props
          function mapDispatchToProps(dispatch, ownProps) {
              return {
                  onIncrement: () => {
                      dispatch(Actions.increment(ownProps.caption));
                  },
                  onDecrement: () => {
                      dispatch(Actions.decrement(ownProps.captions))
                  }
              }
          }
          

          Provider

          import {Provider} from 'react-redux';
          
          

          react-redux庫的提供的Provider幾乎相同,但更加嚴謹;
          react-redux庫要求store必須是一個包含以下三個函數的object:

          • subscribe
          • dispatch
          • getState

          react-redux還提供了componentWillReceiveProps鉤子,用于每次重新渲染時調用

          redux總結 & 與flux的比較

          1. 全局唯一數據源,store
          2. reducer替換狀態樹,而非直接修改值
          3. Provider優化props傳遞
          4. 組件拆解,功能單一化

          react項目常見組織結構

          • ReactApp
            |---reducers // 所有的reducer
            |---actions // 所有的action構造函數
            |---components // 所有的展示組件
            |---containers // 所有的容器組件
          來源:http://www.jianshu.com/p/908af9f49d42


          站長推薦

          1.阿里云: 本站目前使用的是阿里云主機,安全/可靠/穩定。點擊領取2000元代金券、了解最新阿里云產品的各種優惠活動點擊進入

          2.騰訊云: 提供云服務器、云數據庫、云存儲、視頻與CDN、域名等服務。騰訊云各類產品的最新活動,優惠券領取點擊進入

          3.廣告聯盟: 整理了目前主流的廣告聯盟平臺,如果你有流量,可以作為參考選擇適合你的平臺點擊進入

          鏈接: http://www.modern-decoration.com.cn/article/detial/219

          React-redux: React.js 和 Redux 架構的結合

          通過Redux 架構理解我們了解到 Redux 架構的 store、action、reducers 這些基本概念和工作流程。我們也知道了 Redux 這種架構模式可以和其他的前端庫組合使用,而 React-redux 正是把 Redux 這種架構模式和 React.js 結合起來的一個庫

          解決頁面刷新redux數據丟失問題

          對于目前普遍的“單頁應用”,其中的好處是,前端可以從容的處理較復雜的數據模型,同時基于數據模型可以進行變換,實現更為良好的交互操作。良好的交互操作背后,其實是基于一個對應到頁面組件狀態的模型,隨便稱其為UI模型。

          redux 和 mobx 調研結果- mobx

          mobx 不同于 redux 的單一數據源的統一管理,它可以有多個 store, 為了便于維護 ,每一個 store 都是一個類,這樣便于維護和擴展;mobx 不同于 redux 的單一數據源的統一管理

          深入學習和理解 Redux

          Redux官網上是這樣描述Redux,Redux is a predictable state container for JavaScript apps.(Redux是JavaScript狀態容器,提供可預測性的狀態管理)。 目前Redux GitHub有5w多star,足以說明 Redux 受歡迎的程度。

          redux之redux-thunk和redux-saga

          redux作為狀態管理倉庫,在我們前端應用中發揮著非常重要的作用,先放一張官方redux flow圖片,使用middleWare背景:我們知道redux中數據流是同步的,不支持異步action更新或獲取數據,但是在實際項目中異步請求數據絕對是高頻出現,并且可以說占據了9成以上的業務場景

          如何使用24行JavaScript代碼實現Redux?

          Redux是迄今為止創建的最重要的JavaScript庫之一,靈感來源于以前的藝術比如Flux和Elm,Redux通過引入一個包含三個簡單要點的可伸縮體系結構,使得JavaScript函數式編程成為可能。如果你是初次接觸Redux

          基于Hooks 的 Redux 速成課

          你對 Redux 感到困惑嗎?如果使用新的 Redux Hooks,會更加簡單!這里是一個關于 Redux 的速成班,將配合 React 函數組件使用:

          redux和react-redux

          redux是react的狀態管理工具,卻不僅僅只是為了react而生的,所以在使用中會存在痛點。而react-redux是專門為了react定制,目的是為了解決redux的痛點,起到了補充的作用。flux無非就是一個常見的event dispatcher

          動手實現一個react-redux

          react-redux 是 redux 官方 React 綁定庫。它幫助我們連接UI層和數據層。本文目的不是介紹 react-redux 的使用,而是要動手實現一個簡易的 react-redux,希望能夠對你有所幫助。

          帶著問題看React-Redux源碼

          我在讀React-Redux源碼的過程中,很自然的要去網上找一些參考文章,但發現這些文章基本都沒有講的很透徹,很多時候就是平鋪直敘把API挨個講一下,而且只講某一行代碼是做什么的,卻沒有結合應用場景和用法解釋清楚為什么這么做。

          內容以共享、參考、研究為目的,不存在任何商業目的。其版權屬原作者所有,如有侵權或違規,請與小編聯系!情況屬實本人將予以刪除!

          文章投稿關于web前端網站點搜索站長推薦網站地圖站長QQ:522607023

          小程序專欄: 土味情話心理測試腦筋急轉彎幽默笑話段子句子語錄成語大全運營推廣

          国产精品高清视频免费 - 视频 - 在线观看 - 影视资讯 - 唯爱网