redux好難懂,終于明白了一點,做了個小demo,記錄一下。
創(chuàng)新互聯(lián)建站一直通過網(wǎng)站建設和網(wǎng)站營銷幫助企業(yè)獲得更多客戶資源。 以"深度挖掘,量身打造,注重實效"的一站式服務,以成都網(wǎng)站建設、成都網(wǎng)站設計、移動互聯(lián)產(chǎn)品、網(wǎng)絡營銷推廣服務為核心業(yè)務。10年網(wǎng)站制作的經(jīng)驗,使用新網(wǎng)站建設技術(shù),全新開發(fā)出的標準網(wǎng)站,不但價格便宜而且實用、靈活,特別適合中小公司網(wǎng)站制作。網(wǎng)站管理系統(tǒng)簡單易用,維護方便,您可以完全操作網(wǎng)站資料,是中小公司快速網(wǎng)站建設的選擇。
先看目錄結(jié)構(gòu):
src
|--index.js
|--actions
|--index.js
|--components
|--Additem.js
|--App.js
|--ItemList.js
|--reducers
|--index.js
最終效果如圖:
redux三大件:actions , reducers, store ,
Action 是把數(shù)據(jù)從應用(譯者注:這里之所以不叫 view 是因為這些數(shù)據(jù)有可能是服務器響應,用戶輸入或其它非 view 的數(shù)據(jù) )傳到 store 的有效載荷。它是 store 數(shù)據(jù)的唯一來源。一般來說你會通過store.dispatch()
將 action 傳到 store。
這是官方的解釋,我個人的理解是 action就是定義一個事件,但不做任何邏輯上的操作,只是把你需要處理的數(shù)據(jù)和事件綁定到一起,然后等待store進行派發(fā),也就是更新store。就好像定義了一個按鈕的點擊事件 ;
btn.addEventListener(MouseEvent.CLICK,onClickHandle);
這句代碼實際上什么操作也沒有做,只是告訴系統(tǒng)有MouseEvent.CLICK消息的時候應該做什么。
reducer Action 只是描述了有事情發(fā)生了這一事實,并沒有指明應用如何更新 state。而這正是 reducer 要做的事情。
這是官方解釋,我的理解是就像上面說的onClickHandle函數(shù),就是在等待事件被觸發(fā)的時候要執(zhí)行的代碼,當有action被派發(fā)出來的時候,store就會根據(jù)定義來找到這個函數(shù)去執(zhí)行,然后改變store,從而引起react的重新渲染,最終使view發(fā)生改變。
Store 就是把action 和 reducer 聯(lián)系到一起的對象。Store 有以下職責:
維持應用的 state;
提供 getState()
方法獲取 state;
提供 dispatch(action)
方法更新 state;
通過 subscribe(listener)
注冊監(jiān)聽器。
Redux 應用只有一個單一的 store。當需要拆分處理數(shù)據(jù)的邏輯時,使用 reducer 組合 而不是創(chuàng)建多個 store。
我的理解是store就是一個事件監(jiān)聽器加事件派發(fā)器加狀態(tài)記錄器。他會根據(jù)被觸發(fā)的action來找到對應的reducer。
我在寫這個demo的時候是先定義了action,也就是會有哪些操作,然后根據(jù)這些action去寫reducer,也就是每個事件應該怎么處理。最后寫了界面,當然,也可以先寫界面,根據(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ā)生了什么事,當應該添加一條記錄的時候,就把text內(nèi)容保存到數(shù)組中并返回,
這里有幾點需要說明:
1,initalState{} 初始state,里面有一個屬性items,數(shù)組類型,當然可以叫別的名字。
2,aitems的第一個參數(shù)state=[],這里為什么會讓state賦值一個數(shù)組類型呢?不應該是object么?這是 因為在給todos賦值那一句,items:aitems,我對這點的理解是當觸發(fā)事件的時候,redux會自動遍歷todos,然后把state和combineReducers中傳入的對象進行比較,遇到同名屬性,就把state中的同名屬性值傳給combineReducers中的同名屬性所對應的函數(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);
代碼很簡單,一看就能明白,唯一復雜一點的就是最后一句:
export default connect(({items})=>({items}),(dispatch) => ({actions:bindActionCreators(actions,dispatch)}))(App);
connect接收兩個對象,第一個對象是store中的state,也可以是一部分,會變成綁定view的props屬性,第二個對象是actions,也會變成當前view的props屬性,這樣就可以直接調(diào)用同名的actions,會自動派發(fā)對應的事件。connect函數(shù)執(zhí)行過后會返回一個函數(shù),再把當前的view傳進去,就可以把當前的view,state,action綁定到一起,這樣就能在當前的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分別傳進子組件。
5,子組件中有操作,就會調(diào)用actions.
6,actions被觸發(fā),store調(diào)用對應的reducers.
7,reducers被調(diào)用,修改state.
8,react檢測到state被修改,重新渲染組件,改變views。
恩。又跨近了一步。
參考:http://camsong.github.io/redux-in-chinese/docs/basics/ExampleTodoList.html
新聞名稱:node.js學習之react,redux,react-redux
文章源于:http://jinyejixie.com/article48/ppjchp.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站制作、App設計、用戶體驗、App開發(fā)、營銷型網(wǎng)站建設、定制開發(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)