React Router @4.0初学

  • 安装
  • 示例
  • Router组件
    • history
    • MemoryRouter
    • StaticRouter
    • HashRouter
    • BrowserRouter
  • Route组件
    • 是如何渲染的?
    • 属性说明
      • path
      • exact
      • strict
  • Link组件
  • NavLink组件
  • Switch组件

安装

React Router官方git上发布了5个相关的包

|

|

文档地址

|

描述

|
| --- | --- | --- |
| react-router | https://reacttraining.com/react-router/core/guides/quick-start | React Router的核心包,提供核心的路由组件与函数 |
| react-router-dom | https://reacttraining.com/react-router/web/guides/quick-start | 用于 DOM 绑定的 React Router |
| react-router-native | https://reacttraining.com/react-router/native/guides/quick-start | 用于 React Native 的 React Router |
| react-router-redux | https://github.com/ReactTraining/react-router/tree/master/packages/react-router-redux#readme | React Router 和 Redux 的集成 |
| react-router-config | https://github.com/ReactTraining/react-router/tree/master/packages/react-router-config#readme | 静态路由配置的小助手 |

在web项目中(基于浏览器),react-router、react-router-dom两个中只要引用一个就行了,不同之处就是后者比前者多出了 这样的 DOM 类组件。因此建议项目中引用 react-router-dom。

示例

|

import React ``from 'react'

import ``{

BrowserRouter ``as Router``,

Route``,

Link

} from 'react``-``router``-``dom'

const BasicExample ``= (``) =``> (

<``Router``>

<``div``>

<``ul``>

<``li``>``<``Link ``to``=``"/"``>``Home``<``/``Link``>``<``/``li``>

<``li``>``<``Link ``to``=``"/about"``>``About``<``/``Link``>``<``/``li``>

<``li``>``<``Link ``to``=``"/topics"``>``Topics``<``/``Link``>``<``/``li``>

<``/``ul``>

<``hr``/``>

<``Route exact ``path``=``"/" component``=``{``Home``}``/``>

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

<``Route ``path``=``"/topics" component``=``{``Topics``}``/``>

<``/``div``>

<``/``Router``>

)

export default BasicExample

|

Router组件

React Router 4 提供了几种Router组件,BrowserRouter、HashRouter、MemoryRouter、StaticRouter。

history

要想明白这3种组件的区别,我们先从history说起。histoty 是 React Router 4 的两大重要依赖之一(另一个当然是 React 了),在不同的 javascript 环境中, history 以多种形式实现了对会话(session)历史的管理。

我们会经常使用以下术语:

  • "browser history" - history 在 DOM 上的实现,用于支持 HTML5 history API 的浏览器
  • "hash history" - history 在 DOM 上的实现,用于旧版浏览器。
  • "memory history" - history 在内存上的实现,用于测试或非 DOM 环境(例如 React Native)。

4.0之前版本的react-router针对三者分别实现了createHashHistory、createBrowserHistory和create MemoryHistory三个方法来创建三种情况下的history。到了4.0版本,在react-router-dom中直接将这三种history作了内置,于是我们看到了BrowserRouter、HashRouter、MemoryRouter这三种Router,当然,你依然可以使用React-router中的Router,然后自己通过createHistory来创建history来传入。

MemoryRouter

在内存中保存“URL”信息,不会修改浏览器的地址栏,往往用于React Native或测试环境等非浏览器环境。

StaticRouter

从不修改路由

HashRouter

这是之前2.X版本处理浏览器路由的方式,基于url的hash段

|

http:``//localhost``:3333/``#/login

|

BrowserRouter

官方推荐使用的方式,基于url的pathname段

|

http:``//localhost``:3333``/login

|

在react-router 4.0 的文档中有这样一段话:

使用 hash 的方式记录导航历史不支持 location.key 和 location.state。 在以前的版本中,我们为这种行为提供了 shim,但是仍有一些问题我们无法解决。 任何依赖此行为的代码或插件都将无法正常使用。 由于该技术仅用于支持传统的浏览器,因此在用于浏览器时可以使用 代替。

需要注意的是使用后会出现 2 个问题:

  1. 如果你不是通过服务器启动应用,因为chrome自身的安全机制,在本地环境下根本不能用chrome玩。这个不关键,我本地测试换个浏览器还不行么,本地起个服务器也不麻烦。

  2. 关键问题,刷新就是404。原因很简单,BrowserRouter 和 HashRouter 完全不同,前者利用H5的 history 接口,前台路由就是后台收到的路由,例如上面的登录页,在进行刷新时,会去请求服务器的/login资源,但是服务器上根本没这个资源,那么将返回404。所以在使用BrowserRouter时,服务器需要做一些修改,修改的思想就是当收到请求的url不是功能性的,而是前端路由时,重新加载入口html。

    • Apache -> mod_rewrite

    • Nginx -> rewrite

    • Webpack Dev Server -> historyApiFallback

    • Express/Koa/Hapi/etc. -> a wildcard route to your index.html

    下面列举几个例子

    nodejs服务器

    |

    app.use(express.static(path.join(__dirname, 'build')));

    -app.get('/', function (req, res) {

    +app.get('/*', function (req, res) {

    res.sendFile(path.join(__dirname, 'build', 'index.html'));

    });

    |

    apache服务器,.htaccess文件

    |

    Options -MultiViews

    RewriteEngine On

    RewriteCond %{REQUEST_FILENAME} !-f

    RewriteRule ^ index.html [QSA,L]

    |

    gulp + browserSync

    |

    gulp.task(``'browserSync'``, ``function () {

    var proxyOptions = url.parse(``'[http://k1268.mlamp.co/tuning'](http://k1268.mlamp.co/tuning')``);

    proxyOptions.route = ``'/tuning'``;

    browserSync.init({

    server: {

    baseDir: ``'./dist/'``,

    middleware: [proxy(proxyOptions)],

    routes: {

    "/login"``: ``"./dist/"``,

    "/app"``: ``"./dist/"``,

    "/app/todos"``: ``"./dist/"``,

    }

    },

    port: 3333,

    open: ``false``,

    reloadOnRestart: ``true

    })

    // 监听模板html变化

    gulp.watch(config.pug, [``'pug'``])

    // 监听sass变化

    gulp.watch(config.sass, [``'styles'``])

    // 监听image变化

    gulp.watch(config.image, [``'images'``])

    })

    |

组件下只允许存在一个子元素,如存在多个则会报错。

Route组件

组件是React Router中主要的结构单元。在任意位置只要匹配了URL的路径名(pathname)你就可以创建元素进行渲染。

是如何渲染的?

当一个路由的path匹配成功后,路由用来确定渲染结果的参数有三种。只需要提供其中一个即可。

  • component : 一个React组件。当带有component参数的route匹配成功后,route会返回一个新的元素,其为component参数所对应的React组件(使用React.createElement创建)。
  • render : 一个返回React element的函数。当匹配成功后调用该函数。该过程与传入component参数类似,并且对于行级渲染与需要向元素传入额外参数的操作会更有用。
  • children : 一个返回React element的函数。与上述两个参数不同,无论route是否匹配当前location,其都会被渲染。

|

component={Page} />

const extraProps = { color: ``'red' }

render={(props) => (

)}/>

children={(props) => (

props.match

?

:

)}/>

|

的优先级要比高,所以不要在同一个中同时使用这两个属性。

那么Route是如何知道url更新了然后进行重新匹配和渲染的呢?

Route的实现机制:在一个web应用中,改变url无非是2种方式,一种是利用超链接进行跳转,另一种是使用浏览器的前进和回退功能。前者的在触发Link的跳转事件之后触发,而后者呢?Route利用的是我们上面说到过的history的listen方法来监听url的变化。为了防止引入新的库,Route的创作者选择了使用html5中的popState事件,只要点击了浏览器的前进或者后退按钮,这个事件就会触发。

属性说明

  • path

任何可以被 path-to-regexp解析的有效 URL 路径,如果path没有赋值,那么此Route就是默认渲染的。

  • exact

精确匹配,如果为 true,path 为 '/one' 的路由将不能匹配 '/one/two'。

  • strict

对路径末尾斜杠的匹配。如果为 true。path 为 '/one/' 将不能匹配 '/one' 但可以匹配 '/one/two'。

如果要确保路由没有末尾斜杠,那么 strict 和exact 都必须同时为 true

Link组件

如果使用锚点元素实现页面间的切换,在每次点击时页面将被重新加载。React Router提供了组件用来避免这种状况的发生。当你点击时,URL会更新,组件会被重新渲染,但是页面不会重新加载。

参数如下:

|

static propTypes = {

onClick: PropTypes.func,

target: PropTypes.string,

replace: PropTypes.bool,

to: PropTypes.oneOfType([

PropTypes.string,

PropTypes.object

]).isRequired

}

|

replace:跳转的链接是否覆盖history中当前的url,若为true,新的url将会覆盖history中的当前值,而不是向其中添加一个新的。

to:指定需要定位的页面。它的值即可是字符串也可是location对象(包含pathname,search,hash与state属性)。如果其值为字符串将会被转换为location对象。

|

}}>Player #``7``

|

NavLink组件

功能相似,会在匹配上当前URL的时候给已经渲染的元素添加样式参数,组件属性:

  • activeClassName(string):设置选中样式,默认值为 active;
  • activeStyle(object):当元素被选中时, 为此元素添加样式;
  • exact(bool):为 true 时, 只有当地址完全匹配 class 和 style 才会应用;
  • strict(bool):为 true 时,在确定位置是否与当前 URL 匹配时,将考虑位置 pathname 后的斜线;
  • isActive(func):判断链接是否激活的额外逻辑的功能;

Switch组件

React Router 4 的路由默认为“包含”的,这意味着多个 可以同时进行匹配和渲染。如上面示例中




在“/”路由中使用exact进行了精确的路径匹配,如果删掉exact属性的话,那么在访问/About时,将会同时渲染Home组件和About组件,在访问/Topics时,将会同时渲染Home组件和Topics组件。

这种设计,允许我们以多种方式将多个组合到我们的应用程序中,例如侧栏(sidebars),面包屑(breadcrumbs),bootstrap tabs等等。

如果我们只需要在路由列表里匹配一个路由,这时可以使用 来启用排他路由,在给定的 路由中只有一条将渲染:

|

const BasicExample = () => (

  • Home
  • About
  • Topics


exact component={Home}/>

component={About}/>

component={Topics}/>

)

|

你可能感兴趣的:(React Router @4.0初学)