React List - React Router

栏目: IOS · Android · 发布时间: 5年前

内容简介:Create byRecently revised inHello 小伙伴们,如果觉得本文还不错,记得给个star, 小伙伴们的star是我持续更新的动力!

Create by jsliang on 2019-04-26 13:13:18

Recently revised in 2019-04-29 15:25:01

Hello 小伙伴们,如果觉得本文还不错,记得给个star, 小伙伴们的star是我持续更新的动力! GitHub 地址

一 目录

不折腾的前端,和咸鱼有什么区别

目录
5.1 BrowserRouter 语法
5.2 BrowserRouter - basename
5.3 BrowserRouter - getUserConfirmation
5.4 BrowserRouter - forceRefresh
5.5 BrowserRouter - keyLength
6.1 HashRouter - basename
6.2 HashRouter - getUserConfirmation
6.3 HashRouter - hashType
8.1 NavLink - activeClassName
8.2 NavLink - activeStyle
8.4 NavLink - isActive
9.1 MemoryRouter - initialEntries
9.2 MemoryRouter - initialIndex
9.3 MemoryRouter - getUserConfirmation
9.4 MemoryRouter - keyLength
10.4 Redirect - exact
11.1 Route - component
11.3 Route - children
11.6 Route - location
11.7 Route - sensitive
十四 篇外二:Code Splitting
十五 篇外三:Scroll To Top
15.1 跳转页面后滚动到顶部

二 前言

前端路由,是指改变 URL 路径的形式,从而切换到不同的页面,例如:

localhost:3000/home
localhost:3000/user

通过切换不同的 URL,显示不同的页面,从而有了 路由 的概念。

这篇文章我们讲解在 React 中如何通过 React Router 这个插件,灵活使用路由。

jsliang瞎吹的,最好自己百度 前端路由 是啥。

  • 参考资料:
  1. React Router 官方文档
  2. React Router 中文文档
  3. React Router 中文文档(旧)
  4. React Router DOM 中文文档(一) - 简书
  5. React Router DOM 中文文档(二) - 简书
  • 篇外话题:

网上有很多 React Router 文章了,例如:

为何 jsliang 要多次一举?

  1. 你记录你的,我记录我的,互相不妨碍。
  2. 看这些跟看官网没啥两样,所以我需要亲自动手过一遍官网。
  3. 记录我看官网的内容,顺带记录我应用上去的实例,方便我下次回顾。

三 初试

当前版本: "react-router-dom": "^5.0.0"

首先,在 Create React App 中,我们引用 React Router:

  • npm i react-router-dom -S

然后,在 src 目录下新建 pages 用来存放页面,并修改 App.js:

案例:App.js

import React, { Fragment } from 'react';
import { BrowserRouter, Route, Switch, Redirect } from 'react-router-dom';
import ScrollToTop from './components/ScrollToTop';
import Header from './components/Header';
import TimeLine from './pages/TimeLine';
import NotFound from './pages/404';

function App() {
  return (
    <Fragment>
      <BrowserRouter>
        <Header />
        <ScrollToTop>
          <Switch>
            <Redirect from="/" to="/timeline" exact />
            <Route path="/timeline" component={TimeLine}></Route>
            <Route component={NotFound}></Route>
          </Switch>
        </ScrollToTop>
      </BrowserRouter>
    </Fragment>
  );
}

export default App;
复制代码

最后,通过在 App.js 中如此定义,即可定义对应的组件,并渲染对应页面和进行跳转。

四 简介

下面我们拿一些常用的进行介绍:

import { 
  BrowserRouter,
  HashRouter,
  Redirect,
  Route,
  NavLink,
  Link,
  MemoryRouter,
  Switch,
  withRouter
} from "react-router-dom";
复制代码
  1. <BrowserRouter> :路由组件包裹层。 <Route><Link> 的包裹层。
  2. <HashRouter> :路由组件包裹层。相对于 <BrowserRouter> 来说,更适合静态文件的服务器。
  3. <Redirect> :路由重定向。渲染 <Redirect> 将使导航到一个新的地址。
  4. <Route> :路由。定义一个路由页面,用来匹配对应的组件(Component)和路由路径。
  5. <NavLink> :活跃链接。当 URL 中的路径等于该路由定义的路径时,该标签可以呈现它定义的 activeClassName
  6. <Link> :链接。用来跳转到 <Route> 对应的路由(Component) 中。
  7. <MemoryRouter> :暂未使用。 <Router> 能在内存中保存 URL 的历史记录。很适合在测试环境和非浏览器环境中使用,例如 React Native。
  8. <Switch> :路由分组。渲染与该地址匹配的第一个子节点 <Route> 或者 <Redirect> 。可以利用 <Switch> 做分组。
  9. <withRouter> :路由组合。通过 <withRouter> 高阶组件访问 history 对象的属性和最近的 <Route>match 。或者利用它来结合 Redux。

五 BrowserRouter

<BrowserRouter> 会为你创建一个专门的 history 对象,用来记录你的路由,从而能够返回上一页或者跳转到指定的路由页面。

区别于 <HashRouter> ,有响应请求的服务器时使用 <BrowserRouter> ,使用的是静态文件的服务器,则用 <HashRouter>

简单案例:

<BrowserRouter>
  <Header />
  <Route path="/" exact component={TimeLine}></Route>
  <Route path="/timeline" component={TimeLine}></Route>
</BrowserRouter>
复制代码

5.1 BrowserRouter 语法

import { BrowserRouter } from 'react-router-dom'

<BrowserRouter
  basename={optionalString}
  forceRefresh={optionalBool}
  getUserConfirmation={optionalFunc}
  keyLength={optionalNumber}
>
  <App/>
</BrowserRouter>
复制代码

5.2 BrowserRouter - basename

  • 规则: basename: string

为里面的子目录提供基础路径名,例如:

<BrowserRouter basename="/calendar">
  <Link to="/today"/> 
  {/* 渲染为 <a href="/calendar/today"> */}
</BrowserRouter>
复制代码

5.3 BrowserRouter - getUserConfirmation

  • 规则: getUserConfirmation: function

用于确认导航的功能。

// 默认使用 window.confirm。
const getConfirmation = (message, callback) => {
  const allowTransition = window.confirm(message)
  callback(allowTransition)
}

<BrowserRouter getUserConfirmation={getConfirmation}/>
复制代码

5.4 BrowserRouter - forceRefresh

  • 规则: forceRefresh: bool

如果为 true,则路由器将在页面导航中使用整页刷新

const supportsHistory = 'pushState' in window.history
<BrowserRouter forceRefresh={!supportsHistory}/>
复制代码

5.5 BrowserRouter - keyLength

  • 规则: keyLength: number

设置它里面路由的 location.key 的长度。默认为 6。

key 的作用:点击同一个链接时,每次该路由下的 location.key都会改变,可以通过 key 的变化来刷新页面。

<BrowserRouter keyLength={12}/>
复制代码

六 HashRouter

使用 URLhash 部分(即 window.location.hash )的 <Router> 使 UIURL 保持同步。

重要提示 :Hash 历史记录不支持 location.keylocation.state

import { HashRouter } from 'react-router-dom'

<HashRouter>
  <App/>
</HashRouter>
复制代码

6.1 HashRouter - basename

  • 规则: basename: string

所有位置的基本 URL ,格式正确的基本名应该有一个前导斜线,但结尾不能有斜线。

<HashRouter basename="/calendar"/>
<Link to="/today"/> 
{/* 渲染为 <a href="/calendar/today"> */}
复制代码

6.2 HashRouter - getUserConfirmation

  • 规则: getUserConfirmation: func

用于确认导航的功能。默认使用 window.confirm。

// this is the default behavior
const getConfirmation = (message, callback) => {
  const allowTransition = window.confirm(message)
  callback(allowTransition)
}

<HashRouter getUserConfirmation={getConfirmation}/>
复制代码

6.3 HashRouter - hashType

  • 规则: hashType: string

用于 window.location.hash 的编码类型。可用的值是:

  • slash - 创建 #/ 和的 #/sunshine/lollipops
  • noslash - 创建 # 和的 #sunshine/lollipops
  • hashbang - 创建 ajax crawlable ,如 #!/#!/sunshine/lollipops

默认为 slash

七 Link

在应用程序周围提供声明式的,可访问的导航。

7.1 Link - to

  • 规则 1: to: string

链接位置的字符串表示,通过连接位置的路径名,搜索和 hash 属性创建。

<Link to='/courses?sort=name'>字符串形式跳转</Link>
复制代码
  • 规则 2: to: object

一个可以具有以下任何属性的对象:

  • pathname : 表示要链接到的路径的字符串。
  • search : 表示查询参数的字符串形式。
  • hash : 放入网址的 hash ,例如 #a-hash
  • state : 状态持续到 location
<Link to={{
  pathname: '/courses',          // 基础路径
  search: '?sort=name',          // 匹配字段
  hash: '#the-hash',             // 对应内链
  state: { fromDashboard: true } // 未知
}}>
  对象形式跳转
</Link>
复制代码

7.2 Link - replace

  • 规则: replace: bool

如果为 true ,则单击链接将替换历史堆栈中的当前入口,而不是添加新入口。

<Link to="/courses" replace>替换当前 hash 路径</Link>
复制代码

7.3 Link - other

还可以传递想要放在 <a> 上的属性,例如标题, IDclassName 等。

<Link to="/test" id="myTest">测试 1</Link>
复制代码

八 NavLink

一个特殊版本的 Link,当它与当前 URL 匹配时,为其渲染元素添加样式属性。

  • 高亮显示首页: <NavLink to="/timeline" activeClassName="active">首页</NavLink>

8.1 NavLink - activeClassName

  • 规则: activeClassName: string

要给出的元素的类处于活动状态时。默认的给定类是 active 。它将与 className 属性一起使用。

<NavLink
  to="/faq"
  activeClassName="selected"
>FAQs</NavLink>
复制代码

8.2 NavLink - activeStyle

  • 规则: activeStyle: object

当元素处于 active 时应用于元素的样式。

<NavLink
  to="/faq"
  activeStyle={{
    fontWeight: 'bold',
    color: 'red'
   }}
>FAQs</NavLink>
复制代码

8.3 NavLink - exact

  • 规则: exact: bool

如果为 true ,则仅在位置完全匹配时才应用 active 的类/样式。

<NavLink
  exact
  to="/profile"
>Profile</NavLink>
复制代码

8.4 NavLink - isActive

  • 规则: isActive: function

一个为了确定链接是否处于活动状态而添加额外逻辑的函数,如果你想做的不仅仅是验证链接的路径名与当前 URL 的 pathname 是否匹配,那么应该使用它

// 如果链接不仅仅匹配 events/123,而是所有奇数链接都匹配
const oddEvent = (match, location) => {
  if (!match) {
    return false
  }
  const eventID = parseInt(match.params.eventID)
  return !isNaN(eventID) && eventID % 2 === 1
}

<NavLink
  to="/events/123"
  isActive={oddEvent}
>Event 123</NavLink>
复制代码

九 MemoryRouter

<Router> 能在内存中保存 URL 的历史记录(并不会对地址栏进行读写)。很适合在测试环境和非浏览器环境中使用,例如 React Native。

<MemoryRouter>
  <App/>
</MemoryRouter>
复制代码

9.1 MemoryRouter - initialEntries

  • 规则: initialEntries: array

history 栈中的一个 location 数组。这些可能是具有 { pathname, search, hash, state } 或简单的 URL 字符串的完整地址对象。

<MemoryRouter
  initialEntries={[ '/one', '/two', { pathname: '/three' } ]}
  initialIndex={1}
>
  <App/>
</MemoryRouter>
复制代码

9.2 MemoryRouter - initialIndex

  • 规则: initialIndex: number

initialEntries 数组中的初始化地址索引。

9.3 MemoryRouter - getUserConfirmation

  • 规则: getUserConfirmation: function

用于确认导航的函数。在使用 <MemoryRouter> 时,直接使用 <Prompt> ,你必须使用这个选项。

9.4 MemoryRouter - keyLength

  • 规则: keyLength: number

location.key 的长度。默认为 6。

十 Redirect

渲染 <Redirect> 将使导航到一个新的地址。这个新的地址会覆盖 history 栈中的当前地址,类似服务器端(HTTP 3xx)的重定向。

我们可以设置某个路由重定向到另一个路由,例如下面即对 / 完全匹配重定向到 /timeline 页面。

<Redirect from="/" to="/timeline" exact />
复制代码

10.1 Redirect - from

  • 规则: from: string

重定向 from 的路径名。可以是任何 path-to-regexp 能够识别的有效的 URL 路径。

所有匹配的 URL 参数都提供给 to 中的模式。

必须包含在 to 中使用的所有参数。

to 未使用的其他参数将被忽略。

<Switch>
  <Redirect from="/old-path" to="/new-path" />
  <Route path="/new-path" component={Place} />
</Switch>
复制代码

10.2 Redirect - to

  • 规则: to: string

重定向到的 URL ,可以是任何 path-to-regexp 能够理解有效 URL 路径。

to 中使用的 URL 参数必须由 from 覆盖。

<Redirect to="/somewhere/else" />
复制代码
  • 规则: to: object

重定向到的 locationpathname 可以是任何 path-to-regexp 能够理解的有效的 URL 路径。

<Redirect
  to={{
    pathname: "/login",
    search: "?utm=your+face",
    state: { referrer: currentLocation }
  }}
/>
复制代码

10.3 Redirect - push

  • 规则: push: bool

true 时,重定向会将新地址推入 history 中,而不是替换当前地址。

<Redirect push to="/somewhere/else" />
复制代码

10.4 Redirect - exact

  • 规则: exact: bool

完全匹配 from

十一 Route

只要应用程序位置与 Route 的路径匹配,组件就会被渲染。

11.1 Route - component

只有当位置匹配时才会渲染的 React 组件。

<Route path="/user/:username" component={User}/>

const User = ({ match }) => {
  return <h1>Hello {match.params.username}!</h1>
}
复制代码

11.2 Route - render

  • 规则: render: function

这允许方便的内联渲染和包裹,而不是上面那种不想要的重新安装的解释

可以传递一个在位置匹配时调用的函数,而不是使用属性为您创建新的 React element component ,该 render 属性接收所有相同的 route propscomponent 渲染属性。

// 行内编写
<Route path="/home" render={() => <div>Home</div>}/>

// 包裹分开写
const FadingRoute = ({ component: Component, ...rest }) => (
  <Route {...rest} render={props => (
    <FadeIn>
      <Component {...props}/>
    </FadeIn>
  )}/>
)

<FadingRoute path="/cool" component={Something}/>
复制代码

11.3 Route - children

  • 规则: children: function

有时你需要渲染路径是否匹配位置。在这些情况下,您可以使用函数 children 属性,它的工作原理与渲染完全一样,不同之处在于它是否存在匹配。

children 渲染道具接收所有相同的 route props 作为 componentrender 方法,如果 RouteURL 不匹配, match 则为 null ,这允许你动态调整你的 UI 界面,基于路线是否匹配,如果路线匹配我们则添加一个 active 类。

<ul>
  <ListItemLink to="/somewhere"/>
  <ListItemLink to="/somewhere-else"/>
</ul>

const ListItemLink = ({ to, ...rest }) => (
  <Route path={to} children={({ match }) => (
    <li className={match ? 'active' : ''}>
      <Link to={to} {...rest}/>
    </li>
  )}/>
)
复制代码

11.4 Route - path

  • 规则: path: string

任何 path-to-regexp 可以解析的有效的 URL 路径

<Route path="/users/:id" component={User}/>
复制代码

11.5 Route - exact

  • 规则: exact: bool

如果为 true ,则只有在路径完全匹配 location.pathname 时才匹配。

path location.pathname exact matches?
/one /one/two true no
/one /one/two false yes
<Route exact path="/one" component={About}/>
复制代码

jsliang个人经验:

  1. 加了 exact 属性后,会完全匹配路径;如果没有加,则二级路径也会匹配当前路径(例如 /timeline/book )。
<BrowserRouter>
  <Route path="/" exact component={TimeLine}></Route>
  <Route path="/timeline" component={TimeLine}></Route>
</BrowserRouter>
复制代码
  1. 我们可以动态设置 extra 的值,从而判断是否需要加载某个组件。
const Home = () => <div>Home</div>;

const App = () => {
  const someVariable = true;

  return (
    <Switch>
      {/* these are good */}
      <Route exact path="/" component={Home} />
      <Route
        path="/about"
        render={props => <About {...props} extra={someVariable} />}
      />
      {/* do not do this */}
      <Route
        path="/contact"
        component={props => <Contact {...props} extra={someVariable} />}
      />
    </Switch>
  );
};
复制代码

11.6 Route - location

  • 规则: location: object

一个 <Route> 元素尝试其匹配 path 到当前的历史位置(通常是当前浏览器 URL)。但是,也可以通过location 一个不同 pathname 的匹配。

11.7 Route - sensitive

  • 规则: sensitive: bool

如果路径区分大小写,则为 true ,则匹配。

path location.pathname sensitive matches?
/one /one true yes
/One /one true no
/One /one false yes
<Route sensitive path="/one" component={About}/>
复制代码

十二 Switch

渲染与该地址匹配的第一个子节点 <Route> 或者 <Redirect>

可以利用 <Switch> 做分组,即当有匹配时,匹配对应 path 对应的组件;如果没有匹配,则匹配 NotFound 页面。

<BrowserRouter>
  <Header />
  <Switch>
    <Route path="/" exact component={TimeLine}></Route>
    <Route path="/timeline" component={TimeLine}></Route>
    <Route component={NotFound}></Route>
  </Switch>
</BrowserRouter>
复制代码

十三 篇外一:history

history 是一个包,在你安装 React Router 的时候,会作为它依赖包安装到项目中,所以你可以直接使用 history 中的属性和方法:

  • length - ( number 类型) history 堆栈的条目数
  • action - ( string 类型) 当前的操作( push , replace , pop )
  • location - ( object 类型) 当前的位置。 location 会具有以下属性:
    • pathname - ( string 类型) URL 路径
    • search - ( string 类型) URL 中的查询字符串
    • hash - ( string 类型) URL 的哈希片段
    • state - ( object 类型) 提供给例如使用 push(path, state) 操作将
  • location 放入堆栈时的特定 location 状态。只在浏览器和内存历史中可用
  • push(path, [state]) - ( function 类型) 在 history 堆栈添加一个新条目
  • replace(path, [state]) - ( function 类型) 替换在 history 堆栈中的当前条目
  • go(n) - ( function 类型) 将 history 堆栈中的指针调整 n
  • goBack() - ( function 类型) 等同于 go(-1)
  • goForward() - ( function 类型) 等同于 go(1)
  • block(prompt) - ( function 类型) 阻止跳转

十四 篇外二:Code Splitting

随着应用的增长,代码包会随着生长。

到最后你会发现,你打包后的 js 文件大地太多离谱。

所以,我们需要通过代码分割,依据不同的路由,加载不同的 js 文件。

npm i react-loadable -S
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import Loadable from 'react-loadable';

const Loading = () => <div>Loading...</div>;

const Home = Loadable({
  loader: () => import('./routes/Home'),
  loading: Loading,
});

const About = Loadable({
  loader: () => import('./routes/About'),
  loading: Loading,
});

const App = () => (
  <Router>
    <Switch>
      <Route exact path="/" component={Home}/>
      <Route path="/about" component={About}/>
    </Switch>
  </Router>
);
复制代码
  1. 打包项目: npm run build

十五 篇外三:Scroll To Top

15.1 跳转页面后滚动到顶部

  1. 首先 ,在全局 components 文件中定义 ScrollToTop 文件夹,其中 index.js 内容为:
src/components/ScrollToTop/index.js
import { Component } from 'react';
import { withRouter } from 'react-router-dom';

class ScrollToTop extends Component {
    componentDidUpdate(prevProps) {
        if (this.props.location !== prevProps.location) {
          window.scrollTo(0, 0)
        }
    }
    render() {
        return this.props.children
    }
}
 
export default withRouter(ScrollToTop);
复制代码
  1. 然后 ,在 App.js 或者其他页面中使用 ScrollToTop 功能:
src/App.js
import React, { Fragment } from 'react';
import { BrowserRouter, Route, Switch, Redirect } from 'react-router-dom';
import ScrollToTop from './components/ScrollToTop';
import Header from './components/Header';
import TimeLine from './pages/TimeLine';
import NotFound from './pages/404';

function App() {
  return (
    <Fragment>
      <BrowserRouter>
        <Header />
        <ScrollToTop>
          <Switch>
            <Redirect from="/" to="/timeline" exact />
            <Route path="/timeline" component={TimeLine}></Route>
            <Route component={NotFound}></Route>
          </Switch>
        </ScrollToTop>
      </BrowserRouter>
    </Fragment>
  );
}

export default App;
复制代码
  1. 最后 ,我们切换路由的时候,页面就会滚动到顶部。

15.2 页面滚动到顶部

暂未实现

十六 篇外四:Redux

在项目中,我们更希望 React Router 和 React Redux 合并起来,这时候可以:

// before
export default connect(mapStateToProps)(Something)

// after
import { withRouter } from 'react-router-dom'
export default withRouter(connect(mapStateToProps)(Something))
复制代码
  • 参考文献:Redux Integration

十七 总结

如果你纯粹过文档(官方文档, jsliang 的文档),你会觉得毫无趣味、了无生趣、乏味、沉闷……

所以, jsliang 的学法是:开启了一个项目,边翻阅文档,边应用到项目中,并进行 Mark 标记,以便下次使用。

如此,该文档虽然完结了,但是仍未完结!完结的是我过完了官方文档,未完结的是 React Router 在我项目中可能有其他应用,需要我一一添加进来。

jsliang广告推送:

也许小伙伴想了解下云服务器

或者小伙伴想买一台云服务器

或者小伙伴需要续费云服务器

欢迎点击 云服务器推广 查看!

React List - React Router
React List - React Router

React List - React Router

jsliang 的文档库梁峻荣 采用 知识共享 署名-非商业性使用-相同方式共享 4.0 国际 许可协议 进行许可。

基于 github.com/LiangJunron… 上的作品创作。

本许可协议授权之外的使用权限可以从 creativecommons.org/licenses/by… 处获得。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

The Mechanics of Web Handling

The Mechanics of Web Handling

David R. Roisum

This unique book covers many aspects of web handling for manufacturing, converting, and printing. The book is applicable to any web including paper, film, foil, nonwovens, and textiles. The Mech......一起来看看 《The Mechanics of Web Handling》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具