关于javascript:端路由原理及reactrouter的常用组件

4次阅读

共计 4558 个字符,预计需要花费 12 分钟才能阅读完成。

在 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>

 <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>
</body>

通过 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)
正文完
 0