咱們經過一個用戶管理實例來學習react-router-domhtml
這個實例包括9個小組件react
App.js 引入組件數組
Home.js 首頁組件緩存
User.js 用戶管理組件react-router
- UserList.js 用戶列表組件dom
- UserAdd.js 用戶添加組件函數
- UserDetail.js 用戶詳情組件學習
Profile.js 我的中心組件ui
Login.js 用戶登陸組件this
Protected.js 處理登陸的組件(咱們模擬登陸的)
咱們先創建一個App組件,做爲咱們項目引入的組件
import React, {Component} from 'react'; //Router 容器,它是用來包裹路由規則的 //Route 是路由規則 //BrowserRouter基於h5的。兼容性很差 //引入react-router-demo import {HashRouter as Router, Route,Link,NavLink,Switch} from 'react-router-dom'; //引入咱們須要的組件 import Home from "./Home"; import User from "./User"; import Profile from "./Profile"; import Login from "./Login"; import Protected from './Protected' //定義一個App組件 export default class App extends Component { render() { //定義一個咱們選中的狀態 let activeStyle={color:'red'} return ( <Router> <div className="container"> <nav className='nav navbar-default'> <div className="container-fluid"> <a className="navbar-brand">用戶管理</a> </div> <ul className="nav"> <li className='navbar-nav'><NavLink exact activeStyle={activeStyle} to="/">首頁</NavLink></li> <li className='navbar-nav'><NavLink activeStyle={activeStyle} to="/user">用戶管理</NavLink></li> <li className='navbar-nav'><NavLink activeStyle={activeStyle} to="/profile">我的中心</NavLink></li> </ul> </nav> <div> {/*Switch是匹配*/} {/*exact 咱們匹配/斜槓時候,就匹配第一個*/} <Switch> <Route exact path="/" component={Home}/> <Route path="/user" component={User}/> <Protected path="/profile" component={Profile}/> <Route path="/login" component={Login}/> </Switch> </div> </div> </Router> ) } }
App組件使咱們引入的組件,在這個組件裏面,咱們須要注意到最外層的Router
這個是路由容器,咱們路由規則Route須要包裹在日期裏面
Route包含了兩個屬性,path 和 component
path指向的路由路徑,component指向的是要跳轉的組件
咱們路由導航,通常是Link和NavLink兩個
這兩個功能同樣,都是路由跳轉,可是NavLink有一個屬性用來顯示跳轉選中的樣式,activeStyle屬性,寫顯示高亮樣式的,接收一個對象{}
在咱們路由導航有一個to屬性
to屬性是咱們路由的要跳轉的路徑
下面是User.js 組件,主要包含兩個路由NavLink和Route,和上面一個意思,切換兩個組件NavLink和Route
import React, {Component} from 'react' import {Link,Route,NavLink} from 'react-router-dom' import UsersList from './UsersList' import UsersAdd from './UsersAdd' import UserDetail from "./UserDetail"; export default class User extends Component { render() { let activeStyle={color:'red'} return ( <div className='row'> <div className="col-sm-3"> <nav> <ul className="nav nav-stacked"> <li><NavLink activeStyle={activeStyle} to="/user/list">用戶列表</NavLink></li> <li><NavLink activeStyle={activeStyle} to="/user/add">添加用戶</NavLink></li> </ul> </nav> </div> <div className="col-sm-9"> <Route path="/user/list" component={UsersList}></Route> <Route path="/user/add" component={UsersAdd}></Route> <Route path="/user/detail/:id" component={UserDetail}></Route> </div> </div> ) } }
- UserAdd.js 用戶添加組件
import React, {Component} from 'react' export default class UsersAdd extends Component { handleSubmit=()=>{ let username=this.refs.username.value; let password=this.refs.password.value; let user={username,password,id:Date.now()}; let users=JSON.parse(localStorage.getItem('USERS')||"[]"); users.push(user); localStorage.setItem('USERS',JSON.stringify(users)); this.props.history.push('/user/list') } render() { /* * history 用來跳轉頁面 * location.pathname 用來存放當前路徑 * match表明匹配的結果 * * */ return ( <form onSubmit={this.handleSubmit}> <div className="form-group"> <label htmlFor="username" className="control-label"> 用戶名 </label> <input type="text" className="form-control" ref="username" placeholder="用戶名"/> </div> <div className="form-group"> <label htmlFor="username" className="control-label"> 密碼 </label> <input type="password" className="form-control" ref="password" placeholder="密碼"/> </div> <div className="form-group"> <input type="submit" className="btn btn-danger" /> </div> </form> ) } }
咱們將用戶添進去的數據,在頁面緩存,方便咱們用戶列表頁渲染
localStorage.setItem('USERS',JSON.stringify(users));
緩存完成後跳轉到列表詳情頁面userList
this.props.history.push('/user/list')
- UserList.js 用戶列表組件
import React, {Component} from 'react' import {Link} from 'react-router-dom' export default class UsersList extends Component { constructor(){ super(); this.state={users:[]} } componentWillMount(){ let users = JSON.parse(localStorage.getItem('USERS') || "[]"); this.setState({users}); } render(){ return ( <ul className="list-group"> { this.state.users.map((user,index)=>( <li key={index} className="list-group-item"> <span>用戶名:</span> <Link to={`/user/detail/${user.id}`}>{user.username}</Link> <span className="btn btn-danger" onClick={()=>{ let users=this.state.users.filter(item=>item.id!=user.id) this.setState({users}); }}>刪除</span> </li> )) } </ul> ) } }
componentWillMount()是組件掛載完成後的組件周期函數
在這個鉤子函數裏面,咱們去userAdd存儲的USERS數據,而後渲染到頁面上去
<Link to={`/user/detail/${user.id}`}>{user.username}</Link>
這裏面咱們跳轉到我的信息詳情裏面,把每一個人的用戶id帶上
而後咱們用戶詳情頁面UserDetail.js 組件
import React, {Component} from 'react' export default class UserDetail extends Component { render() { // let user=this.props.location.state.user let users = JSON.parse(localStorage.getItem('USERS')||"[]"); let id = this.props.match.params.id; let user = users.find(item=>item.id == id); return ( <table className="table table-bordered"> <thead> <tr> <th>ID</th> <th>用戶名</th> <th>密碼</th> </tr> </thead> <tbody> <tr> <td>{user.id}</td> <td>{user.username}</td> <td>{user.password}</td> </tr> </tbody> </table> ) } }
let id = this.props.match.params.id;
let user = users.find(item=>item.id == id);
經過match裏面獲取到路由帶過來的id
而後判斷users裏面id相同的那一項
而後渲染到頁面上去
,而後咱們判斷登陸,若是沒有登陸,就去登陸,登陸後才能看用戶管理
import React from 'react'; import {Route, Redirect} from 'react-router-dom'; //函數組件 //把屬性對象中的Component屬性取出來賦給comp,把其它屬性取出來賦給other對象 //再把other對象的所有屬性取出來賦給Route // component=組件 // render函數 當路由匹配的時候,渲染的是render方法的返回值 export default function ({component: _comp, ...rest}) { return <Route {...rest} render={ props => localStorage.getItem('login') ? <_comp/> : <Redirect to={{pathname: '/login', state: {from: props.location.pathname}}}/> }/> return null; }
若是沒有登陸,咱們就進入登陸組件,其實咱們模擬登陸就是設置了一個緩存login爲true,模擬權限,真實項目中,咱們經過後臺接口來限制,路由跳轉
import React, {Component} from 'react'; export default class Login extends Component { handleClick = ()=>{ localStorage.setItem('login','true'); console.log(this.props); this.props.history.push(this.props.location.state.from); } render() { return ( <div> <button onClick={this.handleClick} className="btn btn-primary">登陸 </button> </div> ) } }
後面,咱們首頁Hone和Profile兩個組件,基本就是展現我的信息的,就是渲染,因此我就沒有必要寫了!
整體完成,路由嵌套路由,而後經過路由參數分辨路由不一樣的信息