ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

前端路由原理及react-router的常用组件

2021-04-11 22:59:05  阅读:132  来源: 互联网

标签:url react 地址 跳转 组件 router 路由 history


在react中,通常都是使用单页面应用(SPA),即整个页面只有一个html,然后通过不同的url地址进行组件的匹配和切换。

我们看到的url地址可能会有两种形式,一种是 localhost:3000/home,一种是 localhost:3000/#/home,两种地址的区别在于有无#,有#的是根据hash来进行匹配,即url中的锚点,本质上是通过location.hash来改变href,hash后的内容是不会发送给服务器的,没有#是通过html5的history来进行跳转,两者跳转后都不会进行刷新。

以下路由是美团和网易云音乐的,可以看到他们的路由地址的分别是基于hash和history

具体来说,通过#来区分路由的实现原理是监听hash的变化,这里监听的方式是使用hashchange 事件,当url地址发生了变化时,通过匹配当前url的地址来进行展示,代码如下所示

<body>
    <div>
       <a href="#/home">首页</a>
       <a href="#/about">关于</a>
    </div>
    <div id="content"></div>
</body>

<script>
  window.addEventListener('hashchange',()=>{
    const content = document.getElementById('content')
    switch(location.hash){
      case '#/home':
        content.innerHTML = '首页'
        break
      case '#/about':
        content.innerHTML = '关于'
        break  
      default:  
        content.innerHTML = ''
    }
  })
</script>


通过html5的history来实现跳转无刷新,就需要阻止a标签的默认行为,再通过history的pushState这一方法实现url地址的替换,同样是监听url地址的变化,这里使用popState方法,当url地址发生了变化之后,展示对应的内容。

<body>
  <div>
    <div>
      <a href="/home">首页</a>
      <a href="/about">关于</a>
    </div>
    <div id="content">
   </div>
</body>

<script>
  const content = document.getElementById('content')
  const aEles = document.getElementsByTagName('a')

  for (let el of aEles) {
    el.addEventListener('click', (event) => {
      event.preventDefault()
      const href = el.getAttribute("href")
      history.pushState({}, '', href)
      urlchange()
    })
  }

  window.addEventListener('popstate', () => {
    urlchange()
  })

  function urlchange() {
    switch (location.pathname) {
      case '/home':
        content.innerHTML = '首页'
        break
      case '/about':
       content.innerHTML = '关于'
        break
      default:
        content.innerHTML = ''
    }
  }
</script>


以上的锚点和history分别对应了react-router中的HashRouter和BrowserRouter,在react-router中,想要使用路由组件必须在最外层包裹一层HashRouter或者BrowserRouter,来选择想要使用的路由类型,然后才能使用react-router提供的其它组件,react-route中用于web端的库为react-router-dom,以下所有的组件都是从react-router-dom中导出。

下面来说说react-router的常用组件

1、<Link>和<NavLink>,这两个标签都是由a标签的封装,通过to属性指定跳转的链接地址,<NavLink>比<Link>多的是可以指定选中的样式和类名,格式如 

<Link to="/about">关于</Link>

通过<Link>标签,点击之后就可以跳转到指定的地址,此时即使外层包裹的是HashRouter,也不需要自己加上#,react-router会帮我们在url上加上#


2、当使用<Link>定义了跳转的url地址后,此时需要指定匹配跳转该url地址时需要显示的内容,此时使用的是<Route>,通过path属性指定url地址,component属性指定渲染的组件,格式如

 <Route path="/about" component={About} />

加上了之后, /about这个地址显示的就是About这个组件里的内容。<Route>进行的是模糊匹配,一个url路径可能可以匹配多个Route,如果需要严格匹配的话,可以增加一个属性 exact,适合没有二级路由的时候开启。

3、在有很多的Route的情况下,即使在第一个Route匹配到合适的之后,仍然会继续向下匹配,直到最后一个,所以在所有的<Route>外包裹一个<Switch>标签可以让它进行唯一的匹配,匹配到合适的之后就不继续匹配了。

4、当所有的<Route>都无法匹配到url上的地址时,可以定义 <Redirect>组件直接重定向到一个页面,通过to来指定路由地址,这个组件要放置到<Route>的最后面,因为它和<Link>不同,<Link>是点击了之后才会跳转对应的地址,而<Redirect>会直接执行并跳转

<Redirect to="/about"/>

5、通过路由来匹配的组件称为路由组件,<Route path="/about" component={About} />,这里的About就是路由组件,和其它的组件是不一样的,路由组件的props里有一些数据,其中包括三大属性,history、location和match,history可以自定义页面的跳转,location用来获取url地址相关的信息,match可以用作动态路由的匹配。

但一般的组件是没有这些props属性的,如果一般的组件也需要这样一些属性的话,可以通过一个高阶组件 withRouter。如

class myCom extends PureComponent { }
export default withRouter(myCom)


再来说说路由传参

有时候,我们希望在链接上带一个id值或者两个页面之间跳转的时候传递一些参数,这时候有三种路由传参方式

1、params传参

<NavLink to="/detail/1">商品详情</NavLink>
<Route path="/detail/:id" component={Detail}/>
// 如果是自行定义跳转的地址可以通过 this.props.history.push("/detail/1")

此时的id就是动态的,可以在id这个位置传递任意的数值或者字符串,然后通过props里的match对象中的params获取动态匹配的内容


2、search传参

<NavLink to="/detail?id=1">商品详情</NavLink>
<Route path="/detail" component={Detail}/>

// 如果是自行定义跳转的地址可以通过 this.props.history.push("/detail?id=1")

此时相当于在url上添加一个问号进行拼接,需要把地址拼成一种键值对的形式,通过 props里的location对象中的search属性获取从问号开始的匹配内容,这一种路由的匹配方式需要自行解析字符串


3、state传参

<NavLink to={ pathname: "/detail", state: { id: 1} }>商品详情</NavLink>
<Route path="/detail" component={Detail}/>

// 如果是自行定义跳转的地址可以通过 this.props.history.push("/detail", { id: 1})


这样的传递参数方式通过props里的location对象中的state属性来获取传递的值,这种方式的可以直接以对象的形式传递,并且可传递的数据更多,这些参数不会显示在url上用一个小的组合案例展示以上内容

import React, { PureComponent } from 'react'
import { NavLink, Route, Switch, withRouter, Redirect } from "react-router-dom"
import Home from "./pages/Home"
import About from "./pages/About"
import Detail from "./pages/Detail"
import Product from './pages/Product'

class App extends PureComponent {
  jumpToProduct(){
    this.props.history.push('/product')
  }
  render() {
    return (
      <div>
        <NavLink exact to="/">首页</NavLink>
        <NavLink to="/about">关于</NavLink>
        <NavLink to="/detail/1">详情</NavLink>
        <button onClick={e=>this.jumpToProduct()}>商品</button>
        <Switch>
          <Route exact path="/" component={Home} />
          <Route path="/about" component={About} />
          <Route path="/detail/:id" component={Detail} />
          <Route path="/product" component={Product}/>
          <Redirect to="/"/>  
        </Switch>
      </div>
    );
  }
}

export default withRouter(App)

 

标签:url,react,地址,跳转,组件,router,路由,history
来源: https://blog.csdn.net/bingbing1128/article/details/115608583

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有