react+react-router+react-redux全家桶小項目開發過程分享

react-ele-webapp

項目地址 :https://github.com/kliuj/reac...html

run

下載完項目

npm install

而後

npm run dev 便可

基於 react react-router redux 的項目,主要是爲了學習實戰react。數據都是固定的,從餓了麼接口臨時抓的,模擬了一個0-100ms的異步數據延遲,感謝餓了麼。react

如下內容是項目開發的過程和一些思考,按照這個過程至少能保證明現一個相對完整的react全家桶項目webpack

內容參考

react文檔:http://reactjs.cn/react/docs/...

react-router 文檔地址 :https://reacttraining.com/rea...

react-router 中文版參考:http://www.uprogrammer.cn/rea...

redux文檔參考:http://redux.js.org/

redux中文文檔:http://cn.redux.js.org/
git

搭建項目:

創建項目目錄,安裝package.json,配置webpack.config
作好基礎依賴工做,摘自package.json的一部份內容github

"devDependencies": {
        "babel-core": "^6.23.1",
        "babel-loader": "^6.4.0",
        "babel-preset-es2015": "^6.22.0",
        "babel-preset-react": "^6.23.0",
        "html-webpack-plugin": "^2.28.0",
        "jshint": "^2.9.4",
        "jshint-loader": "^0.8.4",
        "react": "^15.2.0",
        "react-dom": "^15.2.0",
        "react-router": "^2.0.0",
        "redux": "^3.6.0",
        "webpack": "^2.2.1",
        "webpack-dev-server": "^2.4.1"
    } //JAVASCRIPT

項目模塊結構組織一些基礎工做

開始進行開發一個項目除了技術選型以外,還有許多基礎東西要先設計好,一個好的組織設計要能夠爲之後的提升工做效率。我這方面還有不少欠缺,目前主要考慮了3個模塊的設計:web

1:後臺接口通訊層:model.js 主要處理統一接口的請求發送和回調,放在一塊兒更有利於後期維護,也增長可閱讀性npm

//接口對應的url,這裏只作演示
    const uris = {
          index_entry : fetchData.index_entry,
          hot_search_words : fetchData.hot_search_words
    }
    //接口調用層
    export default function send(url,postData,successCallback,errCallback){
        //模擬延遲,假接口
        let promise = new Promise(function(resolve,reject){
            setTimeout(function(){
                resolve(fetchData[url])
            },Math.random()*100)
        })
        promise.then(function(data){
            successCallback(data)
        })
    }

2:本地數據緩存維護:baseStore.js 主要處理頁面之間的跳轉返回,增長更多的自主性和擴展性json

// 自動存儲瀏覽記錄
    export function  saveFrom(prop) {
          let name = prop.pagename,
              transit =  prop.location,
              qhfrom = transit.query.qhfrom ,//默認所有返回首頁
              para = transit.query.para ? JSON.parse(transit.query.para) : '';
          if(!qhfrom) return false;
          let paths  = localStorage.getItem("FromUrlStore") ? JSON.parse(localStorage.getItem("FromUrlStore")) : {};
          if (localStorage) {
            paths[name] = {
              'name':qhfrom,//存儲來源頁面
              'para':para //存儲來源頁面的參數
            }
            localStorage.setItem("FromUrlStore", JSON.stringify(paths));
          }
      }
   //存儲頁面的來源,統一管理

3:公共方法的處理:baseFun.js 主要用來定義一些公用的模塊方法redux

//放置公用函數 
    export function showToast(){
        ...
    }

使用react-router初始化頁面

import React from 'react'
     import { render } from 'react-dom'
     import { Router, Route, Link,hashHistory ,IndexRedirect,IndexRoute} from 'react-router'
     import Home from './components/home.jsx'
     import Discover from './components/discover.jsx'
     const App = React.createClass({
       render() {
         return (
           <div>
             <footer>
                 <Link to="/home">外賣</Link> 
                 <Link to="/discover?qhfrom=home">發現</Link>
             </footer>
             {this.props.children}
           </div>
         )
       }
     })
     const route = (
          <Router history={hashHistory}>
             <Route path="/" component={App}>
               <IndexRoute component={Home} />
               <Route path="home" component={Home} />
               <Route path="discover" component={Discover} />
             </Route>
           </Router>
     )
     render(route, document.getElementById("app"))

代碼簡單介紹:
由於沒有後臺,採用的 hashHistoryhash路由),關於hash路由能夠參考:https://github.com/kliuj/spa-... 有簡單的介紹。promise

這個是router的跳轉 <Link to="/home">外賣</Link>
這個是加載子路由組件 {this.props.children}
這個是默認的跳轉頁面 <IndexRoute component={Home} />

處理首頁的滾動列表

首頁主要分紅了4個組件
底部導航 + 滾動列表 + 單個產品 + 首頁搜索框

滾動列表封裝了一個簡單的組件

<List
        list={Pro}  //每一個產品item組件
        pagename={'home'} //跳轉產品列表的上級頁面  用來處理返回
        data={this.state.productList} //須要渲染的數據
        onScroll = {this.getMore.bind(this)}//滾動加載函數
    />
    在scrollList組件裏面監聽了滾動事件進行自動加載的處理

react-redux 處理登陸和登出

使用redux的緣由:用戶信息和登陸是兩個不一樣的組件,也沒有父子級的關係,可是須要進行數據狀態共享和相互影響。詳細信息能夠看上面的官方文檔,我這裏就簡單說一下我這個項目的應用。

定義常量 actionTypes.js

//登入成功
    export const LOG_SUCCESS = 'LOG_SUCCESS'
    //正在登陸
    export const LOG_ING = 'LOG_ING'
    //註銷登陸
    export const LOG_OUT = 'LOG_OUT'
    //主要是統一保存狀態對應的名稱

定義具體的觸發操做 actions/login.js

//註銷 同步
    export function log_out (){
        return {
            type:actionTypes.LOG_OUT
        }
    }
    //登入 異步
    export function log_in (obj){
        return dispatch=>{
            //pending  正在進行登陸的狀態
            dispatch({type:actionTypes.LOG_ING})
            //開始發送異步請求登陸
            new Promise((resolve,reject)=>{
                ...
            }).then(res=>{
                dispatch(res)
            })
        }
    }
    //異步狀態須要使用中間件

處理數據 reducers/login.js

export default function(state = initialData,action){
        switch(action.type){
            case actionTypes.LOG_SUCCESS:
                return {
                    loginstate:1,
                    username:action.username
                }
                break
            case actionTypes.LOG_ING:
                return{
                    loginstate:-1,
                    username:'正在登陸'
                }   
            case actionTypes.LOG_OUT:
                return initialData
                break
            default :
                return initialData  
        }
    }

使用中間件建立store層 store/store.js

import {createStore, applyMiddleware} from 'redux'
    import thunk from 'redux-thunk'
    //合併的多個reducer,解耦
    import rootReducer from '../reducers/index.js'
    const middlewares = [thunk]
    const createStoreWithMiddleware = applyMiddleware(...middlewares)(createStore)
    export default function configureStore(initialState){
        return createStoreWithMiddleware(rootReducer,initialState)
    }

在路由層引入

import {Provider} from 'react-redux'
    const store = configureStore()
    const route = (
      <Provider store={store}>
          <Router history={hashHistory}>
              ...
          </Router>
      </Provider>
    )

組件裏面使用

import { connect } from 'react-redux'
    import {log_out} from '../../actions/login.js' //操做
    ...
    ...
    function mapStateToProps(userinfo){
        let {login} = userinfo //這個是返回的全部reducer,咱們只用當前須要的,參考 reducers/index.js 內容
        return login
    }
    export default connect(mapStateToProps)(UserInfo)
    //這個時候就能夠在當前組件狀態的  this.props 獲取到這個 login 數據,
    //操做的時候  
    const {dispatch} = this.props;
    dispatch(log_out())
    //這時候就能夠操做redux狀態的數據,每次數據改變都會下發給全部接收的組件

以上,咱們就使用了許多東西完成了一個簡單的小項目

相關文章
相關標籤/搜索