node.js學(xué)習(xí)之react,redux,react-redux

redux好難懂,終于明白了一點,做了個小demo,記錄一下。

創(chuàng)新互聯(lián)建站一直通過網(wǎng)站建設(shè)和網(wǎng)站營銷幫助企業(yè)獲得更多客戶資源。 以"深度挖掘,量身打造,注重實效"的一站式服務(wù),以成都網(wǎng)站建設(shè)、成都網(wǎng)站設(shè)計、移動互聯(lián)產(chǎn)品、網(wǎng)絡(luò)營銷推廣服務(wù)為核心業(yè)務(wù)。10年網(wǎng)站制作的經(jīng)驗,使用新網(wǎng)站建設(shè)技術(shù),全新開發(fā)出的標(biāo)準(zhǔn)網(wǎng)站,不但價格便宜而且實用、靈活,特別適合中小公司網(wǎng)站制作。網(wǎng)站管理系統(tǒng)簡單易用,維護(hù)方便,您可以完全操作網(wǎng)站資料,是中小公司快速網(wǎng)站建設(shè)的選擇。

先看目錄結(jié)構(gòu):

src

|--index.js

|--actions

  |--index.js

|--components

  |--Additem.js

  |--App.js

  |--ItemList.js

|--reducers

  |--index.js

最終效果如圖:

node.js學(xué)習(xí)之react,redux,react-redux

node.js學(xué)習(xí)之react,redux,react-redux

node.js學(xué)習(xí)之react,redux,react-redux

redux三大件:actions , reducers, store ,

Action 是把數(shù)據(jù)從應(yīng)用(譯者注:這里之所以不叫 view 是因為這些數(shù)據(jù)有可能是服務(wù)器響應(yīng),用戶輸入或其它非 view 的數(shù)據(jù) )傳到 store 的有效載荷。它是 store 數(shù)據(jù)的唯一來源。一般來說你會通過store.dispatch() 將 action 傳到 store。

這是官方的解釋,我個人的理解是 action就是定義一個事件,但不做任何邏輯上的操作,只是把你需要處理的數(shù)據(jù)和事件綁定到一起,然后等待store進(jìn)行派發(fā),也就是更新store。就好像定義了一個按鈕的點擊事件 ;

btn.addEventListener(MouseEvent.CLICK,onClickHandle);

這句代碼實際上什么操作也沒有做,只是告訴系統(tǒng)有MouseEvent.CLICK消息的時候應(yīng)該做什么。

reducer Action 只是描述了有事情發(fā)生了這一事實,并沒有指明應(yīng)用如何更新 state。而這正是 reducer 要做的事情。

這是官方解釋,我的理解是就像上面說的onClickHandle函數(shù),就是在等待事件被觸發(fā)的時候要執(zhí)行的代碼,當(dāng)有action被派發(fā)出來的時候,store就會根據(jù)定義來找到這個函數(shù)去執(zhí)行,然后改變store,從而引起react的重新渲染,最終使view發(fā)生改變。

Store 就是把a(bǔ)ction 和 reducer 聯(lián)系到一起的對象。Store 有以下職責(zé):

  • 維持應(yīng)用的 state;

  • 提供 getState() 方法獲取 state;

  • 提供 dispatch(action) 方法更新 state;

  • 通過 subscribe(listener) 注冊監(jiān)聽器。

 Redux 應(yīng)用只有一個單一的 store。當(dāng)需要拆分處理數(shù)據(jù)的邏輯時,使用 reducer 組合 而不是創(chuàng)建多個 store。

我的理解是store就是一個事件監(jiān)聽器加事件派發(fā)器加狀態(tài)記錄器。他會根據(jù)被觸發(fā)的action來找到對應(yīng)的reducer。

我在寫這個demo的時候是先定義了action,也就是會有哪些操作,然后根據(jù)這些action去寫reducer,也就是每個事件應(yīng)該怎么處理。最后寫了界面,當(dāng)然,也可以先寫界面,根據(jù)界面定義action。

下面看看代碼是怎么寫的,很簡單并且很簡陋的一段代碼,

src/actions/index.js:

"use strict";

export const ADD_ITEM = 'add_item';
export const DEL_ITEM = 'delete_item';

export function addItem(text){
  return {
    type:ADD_ITEM,
    text
  }
}

export function delItem(index){
  return {
    type:DEL_ITEM,
    index
  }
}

這里定義了兩個事件,一個是添加記錄,一個是刪除記錄,每個方法都是返回一個對象,對象中必須有type屬性,這個type屬性實際上才是真正的事件區(qū)分器,

然后additem中的text是要添加記錄的內(nèi)容,index是要刪除記錄的所引。到這,action就完了。

reducers/index.js:

"use strict";

import { combineReducers } from 'redux';
import { ADD_ITEM, DEL_ITEM } from '../actions/index';

const initalState = {
  items:[]
};

function aitems(state=[],action){
  switch (action.type){
    case ADD_ITEM:
      return state.concat([action.text]);
    case DEL_ITEM:
      state.splice(action.index,1);
      return [...state];
    default:
      return state;
  }
}

let todos=combineReducers({
  items:aitems
});
export default todos;

這個文件里的內(nèi)容就是根據(jù)action做的操作,通過type來區(qū)分發(fā)生了什么事,當(dāng)應(yīng)該添加一條記錄的時候,就把text內(nèi)容保存到數(shù)組中并返回,

這里有幾點需要說明:

1,initalState{} 初始state,里面有一個屬性items,數(shù)組類型,當(dāng)然可以叫別的名字。

2,aitems的第一個參數(shù)state=[],這里為什么會讓state賦值一個數(shù)組類型呢?不應(yīng)該是object么?這是 因為在給todos賦值那一句,items:aitems,我對這點的理解是當(dāng)觸發(fā)事件的時候,redux會自動遍歷todos,然后把state和combineReducers中傳入的對象進(jìn)行比較,遇到同名屬性,就把state中的同名屬性值傳給combineReducers中的同名屬性所對應(yīng)的函數(shù),有點繞!?。。?/p>

3,aitems的第二個參數(shù)action,你想的沒錯,就是剛才我們定義的 src/actions/index.js中的方法所   返回的對象。

4,combineReducers函數(shù)是一個很有個性的函數(shù),不多說了。

src/index.js:

"use strict";
import React from 'react';
import { render } from 'react-dom';
import { createStore } from 'redux';
import { Provider } from 'react-redux';
import  App from './components/App';
import todos from './reducers/index';

let store = createStore(todos);

let element = document.getElementById('app');
render(
  <Provider store={store}>
    <App />
    </Provider>,
  element
);

這個要說的不太多,因為每個講react和redux有關(guān)的文章里大部分會有這一段,主要是為了把react 和redux 通過 react-redux連接起來。

下面看組件:

src/components/App.js:

"use strict";

import React from 'react';
import {connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import  * as actions from '../actions/index';
import AddItem from './AddItem';
import ItemList from './ItemList';

class App extends React.Component{
  render(){
    console.log("app");
    return <div>
      <AddItem onAddClick={(text) => this.props.actions.addItem(text)} />
      <ItemList items={this.props.items} onDelClick={index=>this.props.actions.delItem(index)}/>
      </div>
  }
}
export default connect(({items})=>({items}),(dispatch) => ({actions:bindActionCreators(actions,dispatch)}))(App);

代碼很簡單,一看就能明白,唯一復(fù)雜一點的就是最后一句:

export default connect(({items})=>({items}),(dispatch) => ({actions:bindActionCreators(actions,dispatch)}))(App);

connect接收兩個對象,第一個對象是store中的state,也可以是一部分,會變成綁定view的props屬性,第二個對象是actions,也會變成當(dāng)前view的props屬性,這樣就可以直接調(diào)用同名的actions,會自動派發(fā)對應(yīng)的事件。connect函數(shù)執(zhí)行過后會返回一個函數(shù),再把當(dāng)前的view傳進(jìn)去,就可以把當(dāng)前的view,state,action綁定到一起,這樣就能在當(dāng)前的view中使用state的數(shù)據(jù)和派發(fā)事件了。

然后還有兩個組件:

src/components/Additem.js:

"use strict";
import React from 'react';

export default class AddItem extends React.Component{
  static propTypes = {
    onAddClick:React.PropTypes.func
  };
  _clickHandle(e){
    console.log("additemclick");
    this.props.onAddClick(this.refs.itemText.value.trim());
  }
  render(){
    console.log("additem");
    return <div>
        <input type="text" ref="itemText"/><br/>
        <button onClick={this._clickHandle.bind(this)}>add</button>
      </div>
  }
}

這就是普通的react組件了,從父級接收一些參數(shù)來使用,或者接收一些函數(shù)來實現(xiàn)在子組件中調(diào)用父組件的函數(shù)。

src/components/ItemList.js:

"use strict";

import React from 'react';

export default class ItemList extends React.Component{
  static propTypes={
    items:React.PropTypes.array.isRequired,
    onDelClick:React.PropTypes.func
  };
  _onDelClick(index){
    console.log("itemlistclick",index);
    this.props.onDelClick(index);
  }
  render(){
    console.log("itemlist");
    console.log(this.props.items);
    return <ul>
      {
        this.props.items.map((value,index) =>
          <li>{index},{value}<button onClick={this._onDelClick.bind(this,index)}>del</button></li>
          )}
    </ul>
  }
}

這個,同上,不再多做解釋。

恩。demo到這里,主要代碼就完了,再來梳理一遍:

1,src/index.js把所有的包關(guān)聯(lián)起來。

2,定義actions,定義reducers。

3,把state和actions綁定到App.js上。

4,從App.js中把state和actions分別傳進(jìn)子組件。

5,子組件中有操作,就會調(diào)用actions.

6,actions被觸發(fā),store調(diào)用對應(yīng)的reducers.

7,reducers被調(diào)用,修改state.

8,react檢測到state被修改,重新渲染組件,改變views。

恩。又跨近了一步。

參考:http://camsong.github.io/redux-in-chinese/docs/basics/ExampleTodoList.html

新聞名稱:node.js學(xué)習(xí)之react,redux,react-redux
文章源于:http://muchs.cn/article48/ppjchp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站制作、App設(shè)計、用戶體驗、App開發(fā)、營銷型網(wǎng)站建設(shè)、定制開發(fā)

廣告

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

成都seo排名網(wǎng)站優(yōu)化