react + react-router + react-rudux + webpack

基本环境

  • nodejs(npm)

一.初始化目录

1
2
3
$mkdir react-webpack
$cd react-webpack
$npm init #生成package.json文件

二.安装依赖包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# react,react-dom是React核心包
$npm i --save-dev react react-dom react-transform-hmr redbox-react react-transform-catch-errors
# 使用webpack做前端模块化工具
$npm i --save-dev webpack webpack-dev-server
# babel转换es6语法
$npm i --save-dev babel-core babel-loader babel-preset-react babel-preset-es2015 babel-plugin-react-transform
# 使用sass预编译css
$npm i --save-dev css-loader style-loader sass-loader node-sass
# 使用axios做ajax请求
$npm i --save-dev axios
# react-redux及其middleware
$npm i --save-dev react-redux redux redux-logger redux-thunk
# react-router
$npm i --save-dev react-router-dom

安装完成后package.json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
"devDependencies": {
"babel-core": "^6.26.0",
"babel-loader": "^7.1.2",
"babel-plugin-react-transform": "^3.0.0",
"babel-preset-es2015": "^6.24.1",
"babel-preset-react": "^6.24.1",
"css-loader": "^0.28.7",
"node-sass": "^4.6.1",
"react": "^16.1.1",
"react-dom": "^16.1.1",
"react-transform-catch-errors": "^1.0.2",
"react-transform-hmr": "^1.0.4",
"redbox-react": "^1.5.0",
"sass-loader": "^6.0.6",
"style-loader": "^0.19.0",
"url-loader": "^0.6.2",
"webpack": "^3.8.1",
"webpack-dev-server": "^2.9.4",
"axios": "^0.17.1",
"react-redux": "^5.0.6",
"react-router-dom": "^4.2.2",
"redux": "^3.7.2",
"redux-logger": "^3.0.6",
"redux-thunk": "^2.2.0"
}

psnpm install axios@0.17.1 通过添加版本好安装指定版本

三.webpack配置

react+webpack配置与vue+webpack下的大同小异
根据不同版本查看官方文档配置需求,webpack中文文档

0.基本配置

核心模块:entry,output,module,plugin

  • entry:构建spa或mpa应用时都需要一个或多个入口文件,以便webpack构建内部依赖
  • output:构建完成后webpack的输出配置
  • module:webpack自身只理解js文件。在构建过程中遇到不同的资源如图片,css等,需要通过不通的loader转换
  • plugin:对资源的处理,如压缩文件,提取css文件

文件webpack.config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
module.exports = {
entry: path.resolve(__dirname, './src/app.jsx'), // 指定入口
output: {
path: path.resolve(__dirname, './build'), // 指定出口
filename: 'index.js'
},
module: {
loaders: [
{
test: /\.(js|jsx)$/, // jsx,js文件转换es6为es5loader
exclude: /node_modules/,
loader: 'babel-loader'
},
{
test: /\.(less|css|scss)$/, // 行内css,scss文件loader
loader: 'style-loader!css-loader!sass-loader'
},
{
test: /\.(png|jpg|jpeg)$/, // 图片
use: {
loader: "url-loader",
options: {
limit: 8192
}
}
}
]
},
plugins: [
// TODO
]
}

1.开发环境配置

webpack-dev-server是小型的nodejs服务器,用于本地开发测试

  • 热加载:自动检测文件更改,加载
  • 服务代理(proxy):解决前后端分离时的跨域问题,本地服务器与前端同源,使用本地服务器代理实际后端
  • 本地资源服务(contentBase):方便资源引用

文件webpack.config.dev.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
devServer: {
contentBase: ["./build", "./assets/"], // contentBase中接受一个数组,指定不同的资源目录
historyApiFallback: true,
inline: true,
noInfo: true,
disableHostCheck: true,
port: 4444,
proxy: {
"/api": {
target: 'http://xxx.xxx.xxx', // 代理目标服务器
secure: false,
changeOrigin: true,
}
}
},

2.添加钩子函数

在package.json文件下添加生产,本地环境

1
2
3
4
5
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack",
"dev": "webpack-dev-server --config webpack.config.dev.js"
}

运行

1
2
3
4
# 本地环境
$npm run dev
# 生产环境
$npm run build

四.react相关

react中文文档
react-router中文文档
react-redux中文文档

ps:使用时需要注意版本,不同版本下的api可能不同

1.react-router

react-router4的使用与其他版本的不同

文件route.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import React from 'react'
import {
HashRouter as Router,
Route,
Switch
} from 'react-router-dom'
import Index from './view/index.jsx'
import Movie from './view/movie.jsx'
import MovieList from './view/movieList.jsx'
const route = () => (
<Router>
<Switch>
<Route exact path="/" component={Index}/>
<Route path="/movie/:movieId" component={Movie}/>
<Route path='/movieList' component={MovieList}></Route>
</Switch>
</Router>
)
export default route

Ⅰ.路由方式

  • react-router有BrowserRouter,HashRouter,MemoryRouter,StaticRouter路由组件,其中BrowserRouter,HashRouter在浏览器中使用,实现前端路由功能。
  • BrowserRouter基于url的location.pathname,HashRouter基于location.hash。
  • 在使用BrowserRouter搭建应用时,需要服务器对前端路由路径的修改,以防止跳转后页面再刷新出现404错误。

Ⅱ.嵌套路由

  • react-router4路由与其他版本的不同,router下只能有一个根节点。

Ⅲ.js跳转

  • this.props.history对象实现页面路由跳转

2.react-redux

Ⅰ. 单一状态

  • redux是在应用比较复杂情况下,对整个应用的数据及状态变化集中管理,因此在一个spa应用中应该有且只有一个store。

Ⅱ. 单向数据流

  • 为了便于追踪数据状态的流动过程,redux使用单向数据流管理数据。
  • 对state的更新通过dispatch获取action对象,reducer对action的处理,state改变时通知component做re-render。
  • 在createStore是可以添加中间件

Ⅲ. react-redux

redux与React没有直接关系,需要通过react-redux结合react和redux。react-redux提供Provide与connect功能模块。

  • Provider组件主要将属性(props)直接给子孙component,无须通过props层层传递,从而减少组件的依赖关系。
  • connect方法的主要作用就是让Component与Store进行关联, Store的数据变化可以及时通知Views重新渲染。

文件store.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import { createStore, applyMiddleware } from 'redux'
import thunkMiddleware from 'redux-thunk'
import logger from 'redux-logger'
import reducer from './reducer.js'
//创建一个 Redux store 来以存放应用中所有的 state,应用中应有且仅有一个 store。
var store = createStore(
reducer,
applyMiddleware( // 应用中间件
thunkMiddleware, // 允许我们 dispatch() 函数
logger
)
);
export default store