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 ^_^

相關文章
相關標籤/搜索