React中的路由(react-router-dom)

13,062 阅读5分钟

4.1 react-router-dom4.0 基本介绍

4.1.1 HashRouterBrowserRouter

  • HashRouter: http://localhost:3000/#/admin/buttons
  • BrowserRouter: http://localhost:3000/admin/buttons

4.1.2 Link

import {Link} from 'react-router-dom';

// 方式一
const Header = () => {
  <header>
    <nav>
    <ul>
      <li><Link to="/">Home</Link></li>
      <li><Link to="/about">about</Link></li>
      <li><Link to="/three">three</Link></li>
    </ul>
    </nav>
  </header>
}

// 方式二
<Link to={{ pathname: '/three/7' }}>Three #7</Link>

// 方式三 一个基本的location对象
{pathname: '/', search: '', hash: '', key: 'abc123' state: {}}
// props.match.params.number

定义:<Route path="/about/:number"/>

取值:this.props.match.params.number

4.1.3 Switch

正常4.0会匹配route下面所有路由,如果只想匹配其中一个

使用switch, 匹配其中一个,不再会继续往下匹配

<Switch>
  <Route path='/admin/ui/buttons' component={Buttons} />
  <Route path='/admin/ui/modals' component={Modals} />
  <Route path='/admin/ui/loading' component={Loading} />
  <Route path='/admin/ui/messages' component={Messages} />
  <Route path='/admin/ui/tabs' component={Tabs} />
  <Route path='/admin/ui/gallery' component={Gallery} />
  <Route path='/admin/ui/carousel' component={Carousel} />
</Switch>

4.1.4 Redirect 重定向

<Redirect to="/admin/home"/>

4.2 路由demo演示

4.2.1 混合组件化

index => home => main/about/topics

// /index.js
import React from 'react';
import ReactDOM from 'react-dom';
import Home from './pages/route-demo/route1/Home';

ReactDOM.render(<Home />, document.getElementById('root'));
serviceWorker.unregister();
// route-demo/home
import React, { Component } from 'react';
import {
    HashRouter,
    Route,
    Link,
    Switch
} from 'react-router-dom';
import Main from './main'
import About from './about'
import Topics from './topics'
class Home extends Component {
    constructor(props) {
        super(props);
        this.state = {}
    }
    render() {
        return (
            <HashRouter>
                {/* HashRouter里面一定要有一个根节点,不能直接写Route */}
                <div>
                    <ul>
                        <li><Link to="/">Home</Link></li>
                        <li><Link to="/about">about</Link></li>
                        <li><Link to="/topics">topics</Link></li>
                    </ul>
                    
                    <hr />

                    {/* exact 精准匹配 */}
                    <Route exact path="/" component={Main}></Route>
                    <Route path="/about" component={About}></Route>
                    <Route path="/topics" component={Topics}></Route>
                </div>
            </HashRouter>
        );
    }
}

export default Home;

4.2.2 路由配置化

  • 路由配置化:把路由单独抽取出来,不和link写在一起
  • this.props.children,他表示组件所有的子节点。
  • index => router => home => admin/about/contact
// router.js
class IRouter extends Component {
    constructor(props) {
        super(props);
        this.state = {}
    }
    render() {
        return (
            <BrowserRouter>
                <Home>
                    <Route exact path='/' component={Admin} />
                    <Route path='/about' component={About} />
                    <Route path='/contact' component={Contact} />
                </Home>
            </BrowserRouter>
        );
    }
}

export default IRouter;
// home.js
class Home extends Component {
    render() {
        return (
            <div>
                <ul>
                    <li><Link to='/'>Home</Link></li>
                    <li><Link to='/about'>About Us</Link></li>
                    <li><Link to='/contact'>Contact Us</Link></li>
                </ul>
                <hr />
                {this.props.children}
            </div>
        )
    }
}

export default Home;

4.2.3 嵌套路由

  • 一级路由 index => router => home => admin/about/contact
  • 二级路由 admin => 介绍/文化/人才

// home.js
class Home extends Component {
    render() {
        return (
            <div>
                <ul>
                    <li><Link to='/admin'>Home</Link></li>
                    <li><Link to='/about'>About Us</Link></li>
                    <li><Link to='/contact'>Contact Us</Link></li>
                </ul>
                <hr />
                {this.props.children}
            </div>
        )
    }
}
export default Home;
//router.js
class IRouter extends Component {
    constructor(props) {
        super(props);
        this.state = {}
    }
    render() {
        return (
            <BrowserRouter>
                <Home>
                    {/* 嵌套路由不用写component 写render 继续渲染下一级路由 */}
                    {/* 嵌套路由 不能加exact  否则不能匹配到`/admin` 只能精准匹配到`/` */}
                    <Route path='/admin' render={()=>
                        <Admin>
                            <Route path='/admin/company' component={About} />
                            <Route path='/admin/culture' component={About} />
                            <Route path='/admin/people' component={About} />
                        </Admin>
                    } />
                    <Route path='/about' component={About} />
                    <Route path='/contact' component={Contact} />
                </Home>
            </BrowserRouter>
        );
    }
}
export default IRouter;
// admin.js
class Admin extends Component {
    render() {
        return (
            <div>
                This is Admin Page.
                <ul>
                    <li><Link to='/admin/company'>公司介绍</Link></li>
                    <li><Link to='/admin/culture'>企业文化</Link></li>
                    <li><Link to='/admin/people'>广纳贤才</Link></li>
                </ul>
                <hr />
                {this.props.children}
            </div>
        );
    }
}

export default Admin;

4.2.4 react-router中的 this.props

  • this.props.history

包含了组件可以使用的各种路由系统的方法,常用的有 push 和 replace,两者都是跳转页面,但是 replace 不会引起页面的刷新,仅仅是改变 url。

  • this.props.location

相当于URL 的对象形式表示,通过 search 字段可以获取到 url 中的 query 信息。(这里 state 的含义与 HTML5 history.pushState API 中的 state 对象一样。每个 URL 都会对应一个 state 对象,你可以在对象里存储数据,但这个数据却不会出现在 URL 中。实际上,数据被存在了 sessionStorage 中)

  • this.props.match React 获取 url 参数

包含了具体的 url 信息,在 params 字段中可以获取到各个路由参数的值。

//router.js
class IRouter extends Component {
    constructor(props) {
        super(props);
        this.state = {}
    }
    render() {
        return (
            <BrowserRouter>
                <Home>
                    <Route path='/admin' render={()=>
                        <Admin>
                             {/* :id 可以通过this.props.match.params.id获取动态路由属性值 */}
                            <Route path='/admin/:id' component={Company} />
                        </Admin>
                    } />
                    <Route path='/about' component={About} />
                    <Route path='/contact' component={Contact} />
                </Home>
            </BrowserRouter>
        );
    }
}

export default IRouter;
//company.js
class Company extends Component {
    render() {
        return (
            <div>
                动态路由的值: {this.props.match.params.id}
                {console.log(this.props)}
            </div>
        )
    }
}

export default Company;

4.2.5 404页面

  • <Route component={NoMatch} /> 404页面不用加path=''
//home.js
class Home extends Component {
    render() {
        return (
            <div>
                <ul>
                    <li><Link to='/admin'>Home1</Link></li>
                    <li><Link to='/about'>About Us1</Link></li>
                    <li><Link to='/contact'>Contact Us1</Link></li>
                    <li><Link to='/product'>product</Link></li>
                    <li><Link to='/feedback'>feedback</Link></li>
                </ul>
                <hr />
                {this.props.children}
            </div>
        )
    }
}

export default Home;
//router.js
class IRouter extends Component {
    constructor(props) {
        super(props);
        this.state = {}
    }
    render() {
        return (
            <BrowserRouter>
                <Home>
                    <Switch>
                        <Route path='/admin' render={() =>
                            <Admin>
                                {/* :id 可以通过this.props.match.params.id获取动态路由属性值 */}
                                <Route path='/admin/:id' component={Company}></Route>
                            </Admin>
                        } />
                        <Route path='/about' component={About} />
                        <Route path='/contact' component={Contact} />
                        <Route component={NoMatch}  />
                        <Route component={NoMatch}  />
                    </Switch>
                </Home>
            </BrowserRouter>
        );
    }
}

export default IRouter;
//nomatch.js
class Main extends Component {
    render() {
        return (
            <div>
               404 not found
            </div>
        );
    }
}
export default Main;