React项目引入React-router
安装React-router:
cnpm i react-router-dom --save
一、最基本示例:
在src目录下有index.js、app.js,再新建index.redux.js,分别修改这几个文件的内容如下:
index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import { createStore, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk'
import { Provider } from 'react-redux'
import { BrowserRouter, Route, Link } from 'react-router-dom'
import App from './App';
import { counter } from './index.redux'
// 新建Store,并且以组件属性的形式传入组件里:
const store = createStore(counter, compose(
applyMiddleware(thunk),
window.devToolsExtension ? window.devToolsExtension() : () => {}
)) //compose可以组合函数
applyMiddleware(thunk)
function Erying() {
return <h2>二营</h2>
}
function Qibinglian() {
return <h2>骑兵连</h2>
}
ReactDOM.render(
(<Provider store={store}>
<BrowserRouter>
<ul>
<li>
<Link to='/'>一营</Link>
</li>
<li>
<Link to='/erying'>二营</Link>
</li>
<li>
<Link to='/qibinglian'>骑兵连</Link>
</li>
</ul>
<div>
<Route path='/' exact component={App}></Route>
<Route path='/erying' component={Erying}></Route>
<Route path='/qibinglian' component={Qibinglian}></Route>
</div>
</BrowserRouter>
</Provider>),
document.getElementById('root')
);
app.js:
import React from 'react'
import { connect } from 'react-redux'
import { addGun, removeGun, addGunAsync } from './index.redux'
@connect(
// 把state什么属性放到props里:
state => ({num: state}),
// 把state中的什么方法放到props里,会自动dispatch:
{ addGun, removeGun, addGunAsync },
)
class App extends React.Component {
// constructor(props) {
// super(props)
// }
render() {
// 通过属性获取store以及addGun、removeGun这两个操作函数,再通过store获取初始状态和dispatch方法:
return (
<div>
<h1>现在有机枪{this.props.num}把</h1>
<button onClick={this.props.addGun}>申请武器</button>
<button onClick={this.props.removeGun}>上交武器</button>
<button onClick={this.props.addGunAsync}>拖两天再给</button>
</div>
)
}
}
export default App
index.redux.js:
// 定义常量:
const ADD_GUN = '加机关枪'
const REMOVE_GUN = '减机关枪'
// reducer:
export function counter(state = 0, action) {
switch (action.type) {
case ADD_GUN:
return state + 1
case REMOVE_GUN:
return state - 1
default:
return 10
}
}
// 把对象变成函数返回值:
// action creator,专门创建action:
export function addGun() {
return {type: ADD_GUN}
}
export function removeGun() {
return {type: REMOVE_GUN}
}
// 只要提交action,reducer就会执行,reducer会获取现在的状态和action,action就是{type: ADD_GUN}或{type: REMOVE_GUN},然后判断type,处理完返回新的状态,当状态变化时,用subscribe订阅drender函数会重新执行,重新渲染整个页面
export function addGunAsync() {
return dispatch => {
setTimeout(() => {
dispatch(addGun())
}, 2000)
}
}
二、其他组件:
在src目录下有index.js、app.js、index.redux.js,修改index.js的内容如下:
index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import { createStore, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk'
import { Provider } from 'react-redux'
import {
BrowserRouter,
Route,
Link,
Redirect,
Switch
} from 'react-router-dom'
import App from './App';
import { counter } from './index.redux'
// 新建Store,并且以组件属性的形式传入组件里:
const store = createStore(counter, compose(
applyMiddleware(thunk),
window.devToolsExtension ? window.devToolsExtension() : () => {}
)) //compose可以组合函数
applyMiddleware(thunk)
function Erying() {
return <h2>二营</h2>
}
function Qibinglian() {
return <h2>骑兵连</h2>
}
class Test extends React.Component {
constructor(props) {
super(props)
}
render() {
console.log(this.props)
// this.props.history.push('/')
return <h2>测试组件 {this.props.match.params.location}</h2>
}
}
ReactDOM.render(
(<Provider store={store}>
<BrowserRouter>
<div>
<ul>
<li>
<Link to='/'>一营</Link>
</li>
<li>
<Link to='/erying'>二营</Link>
</li>
<li>
<Link to='/qibinglian'>骑兵连</Link>
</li>
</ul>
<Switch>
<Route path='/' exact component={App}></Route>
<Route path='/erying' component={Erying}></Route>
<Route path='/qibinglian' component={Qibinglian}></Route>
{/*Route组件可用冒号标识参数:*/}
<Route path='/:location' component={Test}></Route>
{/*Redirect组件可以跳转:*/}
<Redirect to='/qibinglian'></Redirect>
</Switch> {/*只渲染命中的第一个Route*/}
</div>
</BrowserRouter>
</Provider>),
document.getElementById('root')
); //Provider组件在应用最外层,传入store,并且只需要用一次,Connect负责从外部获取组件需要的参数,Connect可以用装饰器的方式来写