手挽手带你学React:三档 React-router4.x的运用

手挽手带你学React入门三档,带你学会运用Reacr-router4.x,最先建立属于你的React项目

什么是React-router

React Router 是一个基于 React 之上的壮大路由库,它能够让你向运用中疾速地增加视图和数据流,同时坚持页面与 URL 间的同步。浅显一点就是,它协助我们的顺序在差别的url展现差别的内容。

为何要用React-router

我们开辟的时刻,不可能一切的东西都展现在一张页面上,在营业场景的要求下,我们要依据差别的URL或许差别的哈希来展现差别的组件,这个我们能够称它为路由。在我们不运用React-router的时刻,我们怎样去做路由呢?

我在这里给人人举个例子,不运用React-router,来完成一个简朴路由。

    // App.js
import React,{Component} from 'react'
export default class App extends Component {
    constructor(){
        super()
    // 我们在App.js内部来衬着差别的组件 我们这里采纳哈希路由的体式格局,鉴于React的衬着机制,我们须要把值绑定进入state内部。
        this.state={
            route:window.location.hash.substr(1)
        }
    }
    componentDidMount() {
        // 这里我们经由过程监听的体式格局来监听哈希的变化,而且来更新state增进视图更新
        window.addEventListener('hashchange', () => {
            console.log(window.location.hash.substr(1))
          this.setState({
            route: window.location.hash.substr(1)
          })
        })
      }
    render() {
        //在这里我们定义一个RouterView 一切的变化后的组件都邑丢到这个RouterView中
        let RouterView = App
        switch (this.state.route) {
            case '/children1':
            RouterView = Children
                break;
            case '/children2':
            RouterView = ChildrenTwo
                break;
            default:
            RouterView = Home
                break;
        }
        return (
            <div>    
                <h1>App</h1>
                <ul>
                    <li><a href="#/children1">children1</a></li>  
                    {/* 点击变动哈希值 这里触发我们的监听 然后修正state来触发组件的从新沾染 */}
                    <li><a href="#/children2">children2</a></li>
                </ul>
                <RouterView/>
            </div>
        )
    }
}

// 为了展现效果定义子组件一

class Children extends Component{
    constructor(){
        super()
        this.state={
           
        }
    }
    render(){
        return(
            <div>
                <h1>我是子组件1</h1>
                
            </div>
        )
    }
}

// 为了展现效果定义子组件二

class ChildrenTwo extends Component{
    constructor(){
        super()
        this.state={
        
        }
    }
    render(){
        return(
            <div>
                <h1>我是子组件2</h1>
            </div>
        )
    }
}
// 为了展现效果定义Home组件
class Home extends Component{
    constructor(){
        super()
    }
    render(){
        return(
            <h1>我是Home</h1>
        )
    }
}

如许我们经由过程监听哈希变化的体式格局完成了我们的第一个简朴路由,是不是是关于路由的道理有了那末一丢丢的熟悉呢?接下来我们设想一个场景,这么一个路由涌现了/children1/user/about/1,看到这里是不是是认为,用switch case已蒙B了?我们接下来就要运用到React-router了,这个东西可不须要我们本身去写一大串的switch case了,而且机能啊,整齐度啊等等等方面都比我们本身写的好多了!

React-router 初体验

起首我们在React项目文件目录下实行

npm install react-router-dom --save
npm install react-router --save

要想体验一个新的东西,固然是要拿本身开刀 我们革新上面我们写过的组件

// App.js
import React,{Component} from 'react'
// 起首我们须要导入一些组件...
import { HashRouter as Router, Route, Link } from "react-router-dom";
// 这里有BrowserRouter 和 HashRouter 两种形式  我比较引荐HashRouter来进修 BrowserRouter须要后端合营 零丁前端设置 革新会涌现404
// 然后我们把App组件整顿清洁,也许成这个模样
export default class App extends Component {
    constructor(){
        super()
        this.state={
          
        }
    }
    render() {
        return (
            <Router>
                <div>
                <h1>App</h1>
                <ul>
                    <li> <Link to="/">Home</Link></li>  
                    <li><Link to="/children1/">children1</Link></li>
                    <li><Link to="/children2/">children2</Link></li>
                </ul>
                <Route exact path="/" component={Home} />
                <Route path="/children1" component={Children} />
                <Route path="/children2" component={ChildrenTwo} />
                </div>
            </Router>
        )
    }
}

// 为了展现效果定义子组件一
class Children extends Component{
    constructor(){
        super()
        this.state={
           
        }
    }
    render(){
        return(
            <div>
                <h1>我是子组件1</h1>
            </div>
        )
    }
}
// 为了展现效果定义子组件二
class ChildrenTwo extends Component{
    constructor(){
        super()
        this.state={
        
        }
    }
    render(){
        return(
            <div>
                <h1>我是子组件2</h1>
            </div>
        )
    }
}
// 为了展现效果定义Home组件
class Home extends Component{
    constructor(){
        super()
    }
    render(){
        return(
            <h1>我是Home</h1>
        )
    }
}

这里我们就完成了React-router4.X的开端体验,怎样~我给人人的第一次的觉得还能够吧~

基本组件

Routers
在React-router4.0中,Routers有两个表现体式格局 <BrowserRouter><HashRouter> 这两个标签都将会给你建立一个特地的history对象,BrowserRouter的表现形式须要搭配一个能够响应要求的服务器。HashRouter是静态文件服务器,我们当地开辟的时刻,发起运用HashRouter。这里须要注重一下,BrowserRouter和 HashRouter标签下面,只允许存在一个标签 详细写法以下


<BrowserRouter>
    <div>
        {/*其他内容写在这内里*/}
    </div>
</BrowserRouter>

<HashRouter>
    <div>
        {/*其他内容写在这内里*/}
    </div>
</HashRouter>

Route
注重,最外层的是Router 这里是 Route 这是我们的路由婚配组件,它有两个 Route和Switch
Route 组件具有多个属性,这在我们后期的路由传参中将会用到。这里我们须要简朴相识几个属性 path component exact strict
path 是我们婚配的地点,当地点婚配的时刻 我们才会去衬着 component内的组件内容
path 背面假如誊写形式带了 /: 如许的内容,那末这里将会成为占位符 我们能够应用占位符来取到对应途径的参数 运用 this.props.match.params+占位符的名字 即可拿到
exact 属性来划定我们是不是严厉婚配
strict 则是严厉婚配形式 我们划定的途径运用/one/来誊写 假如没有完整婚配 /one/ 则不会展现

<Route exact path="/one" component={App} />
// 这里我们加了exact 那末 途径完整即是/one的时刻才会衬着App /one/  one  /one/two 背面这三种状况均不会衬着App

// 相反 假如我们没有加 exact 的时刻 /one /one/two  App都邑被衬着

<Route strict path="/one/" component={App} />
// 我们加了 strict 今后 /one 将不会衬着App  而假如没有 strict 这类状况下 /one 是能够衬着App的

同时React-router给我们供应了一个Switch标签 在这个标签内 我们只会衬着一个Route 而且使第一个相符前提的Route 这是什么意思呢?我们来看代码


<Route path="/about" component={About} />
<Route path="/:User" component={User} />
<Route path="/" component={Home} />
<Route component={NoMatch} />

在如许的路由下 我们婚配/about 会发明 一切的路由都能够婚配到而且衬着了出来,这一定不是我们想要的效果 因而我们给它嵌套一个 Switch

<Switch>
    <Route path="/about" component={About} />
    <Route path="/:User" component={User} />
    <Route path="/" component={Home} />
    <Route component={NoMatch} />
</Switch>

这时刻我们就只会婚配到第一个/about,仅仅衬着About,人人依据现实需求去决议是不是嵌套Switch运用

Link和NavLink

Link 重要api是to,to能够接收string或许一个object,来掌握url。我们代码里看看誊写要领

    <Link to='/one/' /> 
    // 这就是路由到one 搭配Router运用 固然我们能够运用一个对象

    <Link to={{
        pathname:'/one',
        search:'?name=qm',
        hash:'#two',
        state:{
            myName:'qimiao'
        }
    }} />
    // 如许我们点击link不仅能够到one 还能够通报一些参数

NavLink 它能够为当前选中的路由设置类名、款式以及回调函数等。运用以下

    <NavLink exact activeClassName='navLink' to='/one/' /> 
    // 这就是路由到one 搭配Router运用 固然我们能够运用一个对象

    <NavLink exact activeClassName='navLink' to={{
        pathname:'/one',
        search:'?name=qm',
        hash:'#two',
        state:{
            myName:'qimiao'
        }
    }} />
    // 这里的exact 一样是严厉比配形式 同Route
    // 如许我们能够为当前选中的路由设置款式了

子路由的誊写

在react-router4之前的版本,子路由经由过程路由嵌套就能够完成了,然则这一个要领到了React-router4中就行不通了

先来一个之前的写法,固然也是毛病示例

export default class App extends Component {
    constructor(){
        super()
        this.state={
          
        }
    }
    render() {
        return (
            <Router>
                <div>
                <h1>App</h1>
                <ul>
                    <li> <Link to="/home">Home</Link></li>  
                    <li><Link to="/children1/">children1</Link></li>
                    <li><Link to="/children2/">children2</Link></li>
                </ul>
                <Route path="/home" component={Home} >
                    <Route path="children1" component={Children} />
                    <Route path="children2" component={ChildrenTwo} />
                    {/*在4.0今后的版本如许都邑报错 那末我们应当怎样写呢*/}
                </Route>
           
                </div>
            </Router>
        )
    }
}

在react-router4.x版本中 我们子路由必需要在子组件内部了

export default class App extends Component {
    constructor(){
        super()
        this.state={
          
        }
    }
    render() {
        return (
            <Router>
                <div>
                <h1>App</h1>
                <ul>
                    <li> <Link to="/home">Home</Link></li>  
                    {/* 一样 这两个link让他们转移到Home中 我们的home组件就变成了下面的模样 */}
                </ul>
                <Route path="/home" component={Home} >
                 {/*<Route path="children1" component={Children} />*/}  
                 {/*<Route path="children2" component={ChildrenTwo} />*/}  
                    {/*先把这里解释掉 然后我们来到Home组件内*/}
                </Route>
           
                </div>
            </Router>
        )
    }
}

// home内部用{this.props.match.url+子路由途径}来猎取当前的途径而且加上我们要路由到的位置来举行路由婚配和途径跳转婚配 如许誊写 Children和ChildrenTwo就是home的子路由了
class Home extends Component{
    constructor(){
        super()
    }
    
    render(){
        return(
            <div>
            <h1>我是Home</h1>
            <li><Link to={`${this.props.match.url}/children1`}>children1</Link></li>
            <li><Link to={`${this.props.match.url}/children2`}>children2</Link></li>
            <Route path={`${this.props.match.url}/children1`} component={Children} />
            <Route path={`${this.props.match.url}/children2`} component={ChildrenTwo} />     
            </div>
        )
    }
}

路由跳转

声明式跳转上面已说过了 Link和NavLink 两个标签就能够满足了 我们重要说一下js跳转
在4.0方才宣布的时刻 this.props.history.push(‘途径’)这个要领已行不通了,不过值得光荣的是,我现在所运用的4.3.1版本又能够运用这个要领来举行js路由跳转了。

我们用home组件来举个例子

class Home extends Component{
    constructor(){
        super()
    }
    toPath=(home)=>{
        console.log(123)
        this.props.history.push({  //我们把要传参的东西都放在push对象内了
            pathname:home,   //我们要抵达哪一个路由
            search:"?a=1",   //明文传参的形式
            query:{'type':'type'}, //query对象传参
            state:{          //state对象传参
                b:456
            }
        })
    // this.props.history.push('/123')
    }
    render(){
        return(
            <div>
            <h1 onClick={()=>{this.toPath(`${this.props.match.url}/children1/123`)}}>我是Home</h1>
            <li><Link to={`${this.props.match.url}/children1`}>children1</Link></li>
            <li><Link to={`${this.props.match.url}/children2`}>children2</Link></li>
            <Route path={`${this.props.match.url}/children1/:id`} component={Children} />
            <Route path={`${this.props.match.url}/children2`} component={ChildrenTwo} />     
            </div>
        )
    }
}

/*响应的 我们在Children 组件内里有对应的要领来猎取参数。*/

class Children extends Component{
    constructor(){
        super()
        this.state={
           
        }
    }
    render(){
        console.log(this.props.match.params.id)  //这类是经由过程途径上面的:id传过来的参数
        console.log(this.props.location.query)  //这是经由过程push的参数对象中的query传过来的 和vue的query有区分 它不在地点栏 革新丧失
        console.log(this.props.location.state)  //这是经由过程push的参数对象中的state传过来的 它不在地点栏 革新丧失
        console.log(this.props.location.search)  //暴露在地点栏,须要自行处理猎取数据


        return(
            <div>
                <h1>我是子组件1 </h1>
            </div>
        )
    }
}

总结

这一期我们重要照样讲了react-router4.x的基本运用和传参要领,react-router4.x坑比较多,不过运用熟练了会让你觉得很爽,人人不要悭吝本身的时候多多进修,博客开通了注册投稿功用,假如人人有好的进修文章,典范总结,能够投稿,能够扫码加我微信请求专栏~谢谢人人的浏览和寓目。

视频制造中

    原文作者:蒋吉兆
    原文地址: https://segmentfault.com/a/1190000018139632
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞