react+react-router4+redux最新版构建分享

      相信不少刚入坑React的小伙伴们有一个一样的疑惑,因为React相关库不断的再进行版本迭代,网上不少之前的技术分享变得再也不适用。好比react-touter2react-router4在写法上存在很多区别,之前的调用方法将没法使得项目正常工做。我最近用React全家桶在构建一个spa,因为官方文档给的比较繁琐,使用相似react-cli的脚手架工具会使你的理解停留在表面,能用单反相机就不用傻瓜相机~~最好仍是本身动手丰衣足食。在这里但愿能用通俗易懂的方式来讲一下如何快速构建spa。(PS:此文旨在让你们少走弯路,所以在项目结构上力求全而简)css


在此以前你先须要懂得基本的 nodejs 操做与 ES2015 语法。
经过npm安装webpack:npm install webpack,而后用node运行配配置文件(这里并不是绝对,也能够直接在cmd里运行,但不推荐)html


首先给出项目结构:vue

--component    //组件文件夹
  ㄴ--hello.jsx    //组件jsx
  --more-component  //嵌套组件能够放在次级目录
--js
  ㄴ--common.js    //本身经常使用的js方法,
--css            
  ㄴ--hello.css   //每一个组件对应一个css文件,便于管理
--img
--route
  ㄴ--router.jsx    //路由配置组件
--store            //redux相关
  ㄴ--action.js     //状态发起动做方法
  ㄴ--reducer.js    //接受动做后改变状态
entry.jsx          //打包入口
temp.html         //打包模板html
webpack.config.js  //webpack配置

项目结构根据我的习惯能够修改,但原则上要保持条理清晰,有时候还要根据项目结构修改webpack配置等。node


接下来配置webpack,同时npm安装所须要的 loaderwebpack相关配置请参考webpack中文文档。本章很少作赘述。
给出一个简单配置:
webpack.config.jsreact

const webpack = require("webpack");
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

const compiler = webpack({
    entry: "./entry.jsx",
    output:{
        path: path.resolve(__dirname, "./dist"),
        filename:"code.min.js"
    },
    module:{
        rules:[
            {
                test:/\.css$/,
                include:[path.resolve(__dirname, "./")],
                loader:"style-loader!css-loader"
            },
            {
                test:/\.js$/,
                include:[path.resolve(__dirname, "./")],
                loader:"babel-loader",
                options: {
                    presets: ['es2015',"stage-0"]
                }
            },
            {
                test:/\.jsx$/,
                include:[path.resolve(__dirname, "./")],
                loader:"babel-loader",
                options: {
                    presets: ['es2015',"stage-0","react"]
                }
            },
            {
                test: /\.(png|jpeg|jpg)$/,
                include:[path.resolve(__dirname, "./img")],
                loader:'file-loader?name=img/[name]-[hash].[ext]'
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template:'./temp.html',
            filename:'./spa.html',
            inject:'body'
        })
    ]
});

const watching = compiler.watch({
    aggregateTimeout: 300,
    poll: undefined
}, (err, stats) => {
    if (err || stats.hasErrors())console.log(stats.compilation.errors);
    else{console.log('success')}
})

当编写好webpack.config.js文件后,咱们只须要用node运行它,那么当咱们的react项目改变时会自行编译到一个自动生成的dist文件夹里(建议必定开启监听文件改变编译,而不是每次改变后手动运行webpack.config.js,由于那样会很慢!)webpack


作好了这些准备工做,接下来正式进入 React 世界:
entry.jsgit

import React from 'react'
import { render } from 'react-dom'
import { createStore } from 'redux'
import todoApp from './store/reducers'
import Main from './route/router.jsx'

let store = createStore(todoApp)

render(
    <Main store={store} />,
    document.body
)

上面import的模块请npm安装,咱们在entry里仅仅建立一个状态管理的store对象,而且将router.jsx的路由模块渲染到body中,reducersredux中具体须要更改哪些状态的js文件,在creatStore里绑定。(关于redux的更多使用方法及理解须要详细具体讲解,涉及篇幅较大,本文暂不涉及,有兴趣能够看文档redux中文文档,我会整理后再单独章节分享)github


接下来咱们将编写路由组件
router.jsxweb

import React from 'react'
import { HashRouter as Router,Route } from 'react-router-dom'
import { Provider } from 'react-redux'

import Hello from '../component/hello.jsx';

class Main extends React.Component {
    render(){
        const { store } = this.props
        return (
            <Router hashType="noslash">
                <Provider store={store}>
                <Route render={({ location }) => {
                    return(
                        <div key={location.pathname} name={location.pathname}>
                            <Route location={location} path="/hello" component={Hello}/>
                        </div>
                    )
                }}/>
                </Provider>
            </Router>
        )
    }
}

export default Main ;

这与react-router2有一些差异,原来的方法已经再也不使用,在react-router4HashRouterBrowserRouter组件从react-redux-dom中引入。vuex


关于业务组件的编写,相信你们都很熟悉,即便之前使用es5开发的小伙伴也应该能很快上手
hello.jsx

import '../css/xxx.css';
import React from 'react';
import { connect } from 'react-redux';
import * as action from '../store/actions';

class Hello extends React.Component{
    constructor(props){
        super(props)
        this.state={...}
    }
    componentDidMount(){
        this.props.dispatch(action.hi())
    }
    render() {
        const { name } = this.props
        return (
            <div>{name}</div>
        )
    }
}

export default connect(state => state)(Hello)

在这个组件里,咱们将redux中管理的state和触发状态更改的dispatch方法经过connect绑定在了props中,能够随时调用,同时该组件将监听reduxstate的变化实时更新数据。


咱们须要改变redux状态时所触发的动做
action.js

export const hi = () => {
    return {
        type:'hi',
        ...//其余你须要的属性
    }
}

根据redux要求,这里的type属性是必须的,不能用别的字段名,不然运行时浏览器会报type不存在。


接收action后执行状态改变的文件就是
reducers.js

import { combineReducers } from 'redux'

const name = (state='', action) => {
    switch (action.type) {
        case 'hi':
            return "hello world!"
        default :
            return state
    }
}

const todoApp = combineReducers({
    name,
    //more state
})  

export default todoApp;

reducer首先用action中传入的type属性来判断咱们要作的是哪一种操做,而后再根据传入的其余属性当作参数作你想要的改变,最后返回一个{name : ...}的对象,而后全部相似的对象经过combineReducers合并为一个总状态对象暴露给组件访问。


当以上文件利用webpack编译打包好之后,一个最简单的react全家桶spa就完成了(虽然只包含一个组件)。
在实际的使用过程当中,须要更多的库来使咱们的应用更强大且美观。好比路由过分动画react-addons-css-transition-group,redux异步更改state数据redux-thunk,Ajax的兼容shimwhatwg-fetch,移动端滚动iscroll等等。

关于react-router4redux的详细用法仍是建议要静下心来理解文档,这样才能在变化无穷的开发需求中运用自如。(我以前也用过vuex,感受相比之下redux文档稍显繁琐,vuex文档看了很容易就理解上手了)

若是感兴趣能够访问个人成熟项目源码React医疗类移动app --Github,欢迎各位多多指教,多多star ^_^

相关文章
相关标签/搜索