react+react-router+react-redux全家桶小项目开发过程分享

react-ele-webapp

项目地址 :https://github.com/kliuj/react-ele-webapp

run

下载完项目

npm install

然后

npm run dev 即可

基于 react react-router redux 的项目,主要是为了学习实战react。数据都是固定的,从饿了么接口临时抓的,模拟了一个0-100ms的异步数据延迟,感谢饿了么。

以下内容是项目开发的过程和一些思考,按照这个过程至少能保证实现一个相对完整的react全家桶项目

内容参考

react文档:http://reactjs.cn/react/docs/getting-started-zh-CN.html

react-router 文档地址 :https://reacttraining.com/react-router/web/guides/quick-start

react-router 中文版参考:http://www.uprogrammer.cn/react-router-cn/index.html

redux文档参考:http://redux.js.org/

redux中文文档:http://cn.redux.js.org/

搭建项目:

建立项目目录,安装package.json,配置webpack.config
做好基础依赖工作,摘自package.json的一部分内容

    "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个模块的设计:

1:后台接口通信层:model.js 主要处理统一接口的请求发送和回调,放在一起更有利于后期维护,也增加可阅读性

    //接口对应的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 主要处理页面之间的跳转返回,增加更多的自主性和扩展性

    // 自动存储浏览记录
    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 主要用来定义一些公用的模块方法

    //放置公用函数 
    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-routers 有简单的介绍。

这个是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状态的数据,每次数据改变都会下发给所有接收的组件

以上,我们就使用了许多东西完成了一个简单的小项目

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容