初入react-redux

來源:互聯網
上載者:User

標籤:

react這麼熱門的架構也不介紹了,redux是一個單項資料流的小架構,當然不只配合react,它起初是為react而配的,現在面向所有了,比如ng-redux的項目。redux做為react的標準搭配,大有超越flux的勢頭。今天show一個例子來入門redux。源碼在此。 (本文預設你已有react基礎,es6基礎)

這個效果很簡單就是一個count計數,+++++的按鈕按一下就會+1;input裡面寫什麼,submit就會alert什麼內容,這個demo很雜亂,是我修改的官方counter的例子,加了一些實驗的東西,比較適合熟悉redux這個東西。

大家都知道,react是由一個個組件構成的,每個組件都是與其他沒有關係的,資料的傳遞都是通過props。redux實現的單項資料流就是為react量身定做的。它維護了一個store,處理一些東西,商務邏輯,資料都在這個store裡面,就把它看成一個操作資料的顯示資料的東西,這個東西把它當作props傳入react組件,然後就可以用來顯示和操作資料了。這個react組件和平常寫的react組件差不多,但是裡面的處理資料是用store,也就是傳入的props處理。詳細的教程請戳redux中文api。

1.首先看一下首頁的html,很簡單,沒什麼東西。裡面這個ul其實沒啥用的,哈哈哈。其實就是一個div,裡面的東西都讓react處理。引入一個bundle.js(webpack壓縮後的檔案)

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>react+redux</title></head>  <body>    <div id="root">        <ul>            <li>l1</li>            <li>l2</li>            <li>l3</li>            <li>l4</li>            <li>l5</li>                </ul>    </div>    <script type="text/javascript" src="bundle.js"></script>  </body></html>

2.主要就是main.js裡的代碼

import {render} from "react-dom"import React from "react"import {Provider} from "react-redux"import configureStore from "./store/configureStore"import App from ‘./containers/app.js‘const store =configureStore();render((<Provider store={store}>    <App /></Provider>    ),document.getElementById(‘root‘)); 

我們看它做了什麼。引入了render,React,Provider,和自己寫的配置store-configureStore,還有經過redux處理過的組件App。render只是es6裡的寫法,也可以換成平常react的寫法,就不列出了。Provider也不用管,只知道redux就是這麼寫組件就可以了,裡面把通過自己建立的store傳入到react組件,然後把處理過的App組件扔在那裡,就完了。主要我們看它的store怎麼建立的,和App怎麼處理的。

3.先看store怎麼處理的。這裡是/store/configureStore.js

import {applyMiddleware,createStore} from "redux";import thunk from "redux-thunk";import reducer from "../reducers/reducer.js"const createStoreWithMiddleware=applyMiddleware(thunk)(createStore)export default function configuerStore(initialStore){    const store=createStoreWithMiddleware(reducer,initialStore);    return store;}

它引入了中介軟體thunk,具體的作用就是讓action可以通過函數的處理,這個中介軟體據說不到10行。詳情看上面連結的教程。可以看到建立store的函數createStoreWithMiddleware(reducer,initialStore);傳入的reducer和initialStore,initialStore是初始的Store狀態,可以隨便取結構,比如本例的store只有一個count欄位,用來儲存count數字。reducer是重要的一點,它是執行商務邏輯的地方,它是一個純函數,任何時候結果都是不變的(傳入相同的東西)。

4.reducer /reducers/reducer.js"

import {combineReducers} from "redux"import { ADD,RED } from ‘../actions/action‘function counter(state=0,action){    switch(action.type){        case ADD: return state+1;        case RED:return state-1;        default:return state;    }}const rootReducer=combineReducers({    counter})export default rootReducer;

combineReducers也不用管,他是組合多個reducer的,用於拆分業務。reducer就是如何改變資料的一個東西,這個counter的函數就是一個reducer,它是通過看action的type的值來操作state的,如果action的type是ADD,state就+1,是RED就-1;它是個純函數,不論你什麼時候傳入相同的action,它輸出都不會變的。這個action又是什嗎?

5.action actions/action.js

export const ADD="ADD"export const RED="RED"export function increment(){    return {        type:ADD    }}export function decrement(){    return {        type:RED    }}export function ince(){    return (dispatch,getState) =>{        //const {counter}=getState()        dispatch(increment());    }}export function dece(){    return (dispatch,getState)=>{        //const {counter}=getState()        dispatch(decrement())    }}

為了簡單,我把官網例子的action改了,就留下加減兩個action。它是什麼呢?你如何改變資料就看它了,它定義的ADD,RED兩個常量,作為type,redux規定action必須有type屬性,別的它不管。redux提供的api只有幾個,其中有dispatch和getState,dispatch是唯一改變state的api,getState是得到當前state,所以dispatch(action)就是改變當前state的方法,我們想增加count,就是dispatch(increment());我們把它封裝成ince()傳遞到組件裡,讓它可以直接改變state,也就是每次點擊+++++就執行一下ince()這樣就可以了。

總結一下,這就是整個store了,它建立了一個store,傳入了reducer(怎麼根據action資料),reducer裡包含了action(改變什麼資料,具體怎麼改)。把這個store傳入組件App,就能通過props裡面的方法改變count了。

6.經過redux修飾的組件

看main.js裡面直接把封裝的App展現出來了,我們看它怎麼處理的App  /containers/app.js

import {bindActionCreators} from "redux"import {connect} from "react-redux"import App from ‘../component/App.js‘import *as Actions from ‘../actions/action‘function mapStateToprops(state){    return {        counter:state.counter    }}function mapDispatchToProps(dispatch){    return bindActionCreators(Actions,dispatch)}export default connect(mapStateToprops,mapDispatchToProps)(App)

bindActionCreators,惟一使用 bindActionCreators 的情境是當你需要把 action creator 往下傳到一個組件上,卻不想讓這個組件覺察到 Redux 的存在,而且不希望把 Redux store 或dispatch傳給它。它把所有的Action都封裝了。 bindActionCreators 把action裝上一層

這裡的App組件就是普通react組件,修飾它的方法就是connect。我們看connect幹了什麼。

connect傳入兩個函數為參,第一個參數的名字mapStateToprops,也很清楚了,你需要把state裡的什麼放到props裡,這裡就只有counter一個欄位。第二個mapDispatchToProps,把dispatch傳入到props,讓組件可以調用dispatch來改變資料的結構,然而有bindActionCreators,就不用dispatch了,而且我們還在action裡封裝的ince(),裡面就是dispatch增加的action,也不用dispatch了。

把資料,怎麼修改資料傳到props裡,然後就可以用了。

最後看一下App這個組件,怎麼用資料和怎麼修改資料呢?

7.APP /component/App.js

import {render} from "react-dom"import React from "react"class App extends React.Component {    constructor(props){        super(props);        this.handleClick=this.handleClick.bind(this);        this.onSubmit=this.onSubmit.bind(this);    }    handleClick(){        const {ince,dece,counter} = this.props;        ince();    }    onSubmit(event){        alert(this.refs.text.value);    }    render() {        const {ince,dece,counter} = this.props;        return(             <form onSubmit={this.onSubmit}>                <input ref=‘text‘ type="text" />                <div>{counter}</div><input type="button" onClick={this.handleClick} value="++++++++++" />                <button>submit</button>            </form>            )    }} class Bpp extends React.Component{     render(){        return (            <div>{this.props.fuk}            </div>)    }}class Cpp extends React.Component{    render(){    const {ince,dece,increment,decrement,counter} =this.props;    const id=this.props.params.id        return (            <div>this is cpp id為{id}</div>)    }}export default App;

Bpp和Cpp沒有顯示出來,只是用作實驗,刪掉也沒事。(我只是忘記刪了)

這裡寫組件是用es6的寫法寫的。es6封裝了原生js的prototype操作,然而它是個不完全的文法糖,因為在裡面不能寫屬性,public property也不行。

引入了React,render相當於ReactDOM.render。組件用extends關鍵字繼承React.Componet,其實還可以用React.createClass,其實是一樣的。後者還是有很多react開發人員使用的,因為它比較方便,為啥說比較方便,後面再提。

看一下這個jsx,就是一個form表單,提交觸發submit事件,一個輸入框,一個+++++的按鈕,一個div裡面是{counter},這樣顯示資料。

 值得一提的是const {ince,dece,counter} = this.props;把props傳的東西拿出來。拿出來什麼呢?資料和如何修改資料的東西。這裡只拿出了ince和dece,他們是我們封裝的action,在裡面dispatch了,你就直接用它操作資料就可以了。counter是我們的資料,在div裡{counter}就顯示了。

onSubmit={this.onSubmit},submit執行自身定義的事件,彈出this.refs.text的值,也就是input的值。

還有注意的就是constructor裡面的東西了,這個東西是在class繼承的時候執行的,super(props);是必有的,如果不寫也會自動給你加上,就是執行一遍父類的this。要注意的是

this.handleClick=this.handleClick.bind(this);
this.onSubmit=this.onSubmit.bind(this);

這兩個必須要綁定一下this,不然在這兩個函數裡取不到this,這很坑的,而且還很麻煩。再加上es6的class功能並不完善,有的地方替代不了js的原型操作,這也就促成了很開發人員用React.createClass寫,組件生命週期事件還可以直接用,自然是比較方便的。

 

總結,這就是整個例子的代碼了,

 

 這裏手繪了一幅圖,主程式分為建立store和修飾app兩部分,主程式main.js將他們弄到一塊就完成了react-redux的例子。裡面用的一些api沒有詳細講解,詳情看上面給出的redux中文api的連結。

webpack裡面沒有用任何複雜的工具,僅僅是用babel轉換了一下es6,其他就沒有什麼了。

 

初入react-redux

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.