项目结构如下:
项目代码提交网址: https://github.com/xiaohao198623/router.git
index.js代码吐下:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
ReactDOM.render(<App />, document.getElementById('root'));
registerServiceWorker();
app.js代码吐下:
import React, { Component } from 'react';
import {HashRouter as Router } from 'react-router-dom'
import RouterView from './router/Router'
import Nav from './containers/Nav'
class App extends Component {
componentWillMount (){
console.log('===========app')
console.log(this.props)
}
render() {
return (
<div>
<Router>
<div>
<Nav></Nav>
<RouterView ></RouterView>
</div>
</Router>
</div>
);
}
}
export default App;
nav.js代码吐下:
import React,{Component} from 'react'
import { Link , withRouter ,NavLink } from 'react-router-dom'
export default class Nav extends Component{
componentWillMount (){
console.log('===========nav')
console.log(this.props)
}
render(){
// console.log(this.props)
return (
<div>
<ul className="nav nav-tabs">
<li role="presentation"><NavLink to={'/'}>首页</NavLink></li>
<li role="presentation"><NavLink to={'/profile'}>个人中心</NavLink></li>
<li role="presentation"><NavLink to={{pathname:'user' }}>用户中心</NavLink></li>
</ul>
{/*<button onClick={()=>{ console.log(this.props); this.props.history.push('/profile') }}>测试按钮</button>*/}
</div>
)
}
}
// export default withRouter(Nav)
Router.js代码吐下:
import React, {Component} from 'react';
//路由的2种形式: hash(HashRouter) , H5的historyApi(BroswerRouter)是路由的容器,是组件,要包在路由的外面
import { Route, Switch, Redirect } from 'react-router-dom'
// import {Home} from './containers/Home',写法错误,错误原因如下解释
import Home from '../containers/Home'
import Profile from '../containers/Profile'
import User from '../containers/User'
import Details from '../containers/Details'
import ProtectedRouter from '../containers/ProtectedRouter'
export default class RouterView extends Component {
componentWillMount (){
console.log('===========router')
console.log(this.props)
}
render() {
return (
<div className={'container'}>
<div className="row">
<div className="col-md-12">
{/*Switch 让router匹配后就停止匹配下面的,这个时候访问下面的3个路由时,出现的都是home组件 */}
<Switch >
{/*exact确切的,表示只有路径完全相同时,才会匹配*/}
<Route path='/' exact={true} component={Home}></Route>
<Route path={'/profile'} component={Profile}></Route>
{/*<Route path={'/user'} component={User}></Route>*/}
<ProtectedRouter path={'/user'} component={User}></ProtectedRouter>
{/*进入详情页面需要传入一个id, details/:id this.props.match.params={ id:1 } , ID必须要有;但是可以随机*/}
<Route path={'/details/:id'} component={Details}></Route>
<Redirect to={'/'}></Redirect>
{/*Redirect具有重定向功能,路由变成首页路由,如果想路由不变,但是组件仍然指向home,可以这么实现*/}
{/*<Route component={Home}></Route>*/}
</Switch>
</div>
</div>
</div>
);
}
}
Home.js代码吐下:
import React,{Component} from 'react'
export default class Home extends Component{
// constructor(){
// super()
// }
render(){
return (
<div>首页</div>
)
}
}
Profile.js代码吐下:
import React,{Component} from 'react'
export default class Profile extends Component{
componentWillMount (){
console.log('===========profile')
console.log(this.props)
}
render(){
return (
<div>个人中心</div>
)
}
}
User.js代码吐下:
import React, {Component} from 'react'
import { Link, Route ,NavLink} from 'react-router-dom'
import Add from '../containers/Add'
import List from '../containers/List'
export default class User extends Component {
render() {
return (
<div className={'container'}>
<div className="row">
<div className="col-md-3">
<ul className="nav nav-staked">
<li role="presentation"><NavLink to={'/user/add'}>添加用户</NavLink></li>
<li role="presentation"><NavLink to={'/user/list'}>用户列表</NavLink></li>
</ul>
</div>
<div className="col-md-9">
{/*<Route path={'/user'} exact={true} component={Add}></Route>*/}
<Route path={'/user/add'} component={Add}></Route>
<Route path={'/user/list'} component={List}></Route>
</div>
</div>
</div>
)
}
}
Details.js代码吐下:
import React,{Component} from 'react'
export default class Details extends Component{
render(){
return (
<div>
{ console.log(this.props) }
<p>{ this.props.match.params.id }</p>
<p>{ this.props.location.state }</p>
</div>
)
}
}
ProtectedRouter.js代码吐下:
import React,{Component} from 'react'
import { withRouter } from 'react-router-dom'
// withRouter是一个高级组件,使用它之后,可以多出来3个属性:history , match ,location。路由组件中无须使用它包裹组件;只有非路由组件,跳转的时候才需要使用它
class ProtectedRouter extends Component{
componentWillMount (){
console.log('===========ProtectedRouter')
console.log(this.props)
let flag=false
if(flag){
this.props.history.push('/')
}
}
render(){
let {path,component:Component}=this.props
return (
<div>
<Component></Component>
</div>
)
}
}
export default withRouter(ProtectedRouter)
Add.js代码吐下:
import React,{Component} from 'react'
export default class Add extends Component{
componentWillMount (){
console.log('===========add')
console.log(this.props)
}
handleClick=()=>{
let userList= JSON.parse(localStorage.getItem('userList')) || []
userList.push({'userId':Math.random() , 'value':this.x.value})
localStorage.setItem('userList', JSON.stringify(userList) )
//素有通过路由渲染的组件属性会多出来3个属性:history,match,loaction
console.log(this.props)
this.props.history.push('/user/list')
}
render(){
return (
<div>
<input type="text" ref={(x)=>{this.x=x}}/>
<button onClick={this.handleClick} >按钮</button>
</div>
)
}
}
List.js代码吐下:
import React, {Component} from 'react'
import { Link} from 'react-router-dom'
export default class List extends Component {
handleClick=(index)=>{
console.log(index)
this.props.history.push('/profile')
}
render() {
let userList = JSON.parse(localStorage.getItem('userList')) || []
// console.log(userList)
return (
<div>
<table className="table table-bordered">
<tbody>
<tr>
<th>用户ID</th>
<th>用户名称</th>
<th>跳转(拼接)</th>
<th>编辑(JSX语法)</th>
<th>函数调用(函数调用)</th>
</tr>
{
userList.map((item, index) => {
return (
<tr key={index}>
<td>{item.userId}</td>
<td>{item.value}</td>
{/*第一种方式:拼接字符串,*/}
<td> <Link to={{
pathname:'/details/'+item.userId ,
//刷新以后,这个状态就消失了
state:index
}}>编辑</Link> </td>
{/*第二种方式:JSX语法*/}
<td> <Link to={`/details/${item.userId}`}>编辑</Link> </td>
{/*React里的事件参数传递和传统的JS参数有些不一样,需要通过bind方法来绑定参数,第一个参数指向this,第二个参数开始才是事件函数接收到的参数;*/}
<td ><span onClick={this.handleClick.bind(this,index)}>编辑</span> </td>
</tr>
)
})
}
</tbody>
</table>
</div>
)
}
}