4 react router_react-router4 - CSDN
  • ReactRouter 4 前瞻

    2016-09-21 08:32:42
    ReactRouter 4 这次改动挺大的,后面又要折腾一次了!!作者:杨森链接:https://zhuanlan.zhihu.com/p/22490775要问用 React 技术栈的前端同学对哪个库的感情最复杂,恐怕非 ReactRouter 莫属了。早在 React 0.x ...
    ReactRouter 4 这次改动挺大的,后面又要折腾一次了!!


    作者:杨森
    链接:https://zhuanlan.zhihu.com/p/22490775

    要问用 React 技术栈的前端同学对哪个库的感情最复杂,恐怕非 ReactRouter 莫属了。早在 React 0.x 时代,ReactRouter 就凭借与 React 核心思想一致的声明式 API 获得了大量开发者的喜爱。后续更是并入 reactjs group 并有 React 核心开发成员参与,俨然是 React 官方路由套件一样的存在。

    然而从 1.x 版本起,ReactRouter 的洪荒之力就开始慢慢爆发,目前最稳定的版本已经是 2.8.1,而下一个正式版本将是 —— 没错,正如你在标题里看到的那样 —— 4.0.0。先收拾一下你崩溃的心情,让我们来看看这一切到底是怎么回事。

    ReactRouter 3 去哪儿了

    从 2.x 直接跨入 4.x,ReactRouter 的 maintainer 数学还不至于那么差,那这一切都是为什么呢?事实上 3.x 版本相比于 2.x 并没有引入任何新的特性,只是将 2.x 版本中部分废弃 API 的 warning 移除掉而已。按照规划,没有历史包袱的新项目想要使用稳定版的 ReactRouter 时,应该使用 ReactRouter 3.x。

    目前 3.x 版本也还处于 beta 阶段,不过会先于 4.x 版本正式发布。如果你已经在使用 2.x 的版本,那么升级 3.x 将不会有任何额外的代码变动。

    为什么又要大改 API

    ReactRouter 的 API 是出了名的善变,这一点我已经在之前的博文中吐槽过一次了。没想到连 React 都稳定的在 15.x 版本中维护了这么久,ReactRouter 还是想要搞点大新闻。

    根据 ReactRouter 核心开发者 ryanflorence 的说法,ReactRouter 4.x 之所以要大刀阔斧的修改 API,主要是为了『声明式的可组合性(Declarative Composability)』。怎么理解声明式的可组合性呢?实际上当你在写 React 组件时,就不知不觉的利用了这一特性。

    function ComponentA() {  
      return <div>A</div>;
    }
    
    function ComponentB() {  
      return <div>B</div>;
    }
    
    function Page() {  
      return <div><ComponentA /><ComponentB /></div>;
    }
    

    正如上面的代码片段,在 Page 组件中你可以方便的将任意组件在 render 方法中渲染出来。但是这种特性遇到 ReactRouter 时,你只能把匹配当前路由的组件用this.props.children(最早的时候是 this.props.routerHandler,有多少人还有印象)渲染 。

    此外,ReactRouter 虽然宣称是声明式的路由库,但仍然提供了不少非声明式的 API,其中路由组件的生命周期方法就是最典型的例子。其实我们不难想到,明明用来渲染的 React 组件本身已经有了一套完备的生命周期方法(componentWillMount、componentWillUnmount 等),为什么还需要 ReactRouter 提供的什么 onEnter 和 onLeave 呢?

    当然,这一切都是 ryanflorence 个人的说法,不知道又有多少人真的会为了追求纯正的 declarative 花时间去重构代码兼容 ReactRouter 4 呢?

    ReactRouter 4 有什么变化

    虽然目前还是 alpha 版本,但是 ReactRouter 4 的 API 已经有了雏形,其官方文档也有不少带 demo 的例子,下面简单总结一下 ReactRouter 4 的变化。

    更少的 API

    先来看看目前 ReactRouter 2 的 API 列表:


    再看看 4.x 计划中的 API:

    直观看起来 API 确实少了不少,但这也意味着使用了被废弃的 API 将会有更大的重构工作量。不,实际上即使用了没有被废弃的 API,也会有很大的重构工作量。但是对于新手来说,学习成本相对会比较低。

    <Router> 变身为容器

    在目前的 API 中,<Router> 组件的 children 只能是 ReactRouter 提供的各种组件,如 <Route>、<IndexRoute>、<Redirect>等。而在 ReactRouter 4 中,你可以将各种组件及标签放进 <Router> 组件中,他的角色也更像是 Redux 中的 <Provider>。

    不同的是 <Provider> 是用来保持与 store 的更新,而 <Router> 是用来保持与 location 的同步。

    以下为新版 ReactRouter 可能的用法:

    <Router>  
      <div>
        <h2>Accounts</h2>
        <ul>
          <li><Link to="/netflix">Netflix</Link></li>
          <li><Link to="/zillow-group">Zillow Group</Link></li>
          <li><Link to="/yahoo">Yahoo</Link></li>
          <li><Link to="/modus-create">Modus Create</Link></li>
        </ul>
    
        <Match pattern="/:id" component={Child} />
      </div>
    </Router>  
    

    不过这样的变动将会导致一个很严重的问题:由于路由定义里不再是纯粹的路由相关的组件,你无法在一个文件中(通常是用来定义路由的 routes.js)看到整个 App 的路由设计及分布。

    目前 ReactRouter 提供了一个工具库来解决将完整的路由定义转换为 <Match> 组件的问题,但是粗略的看了一下用法感觉还是比较别扭,期待正式发布时能有更好的解决方案。

    再见 <Route>,你好 <Match>

    ReactRouter 中被使用最多的 <Route> 组件这次没有幸免,取而代之的是 <Match> 组件。那么 <Match> 究竟有什么不同呢?

    1. pattern 取代 path

    很大程度上这只是为了配合 Match 这个名称的转换而已,实际功能与 path 无异。

    <Match pattern="/users/:id" component={User}/>  
    

    2. component 还是 component,components 没了

    判断路由命中时该渲染哪个组件的 props 还是叫 component,但是为一个路由同时提供多个命名组件的 props components 没有了。下文会详细介绍在 ReactRouter 中如何解决一个路由下渲染多个组件的问题。

    3. 使用 render 渲染行内路由组件

    能够更自由的控制当前命中组件的渲染,以及可以方便的添加进出的动画。

    // convenient inline rendering
    <Match pattern="/home" render={() => <div>Home</div>}/>
    
    // wrapping/composing
    const MatchWithFade = ({ component:Component, ...rest }) => (  
      <Match {...rest} render={(matchProps) => (
        <FadeIn>
          <Component {...matchProps}/>
        </FadeIn>
      )}/>
    )
    
    <MatchWithFade pattern="/cool" component={Something}/>  
    

    <Miss> 取代曾经的 <NotFoundRoute>

    早在 0.x 时代,ReactRouter 提供了 <NotFountRoute> 来解决渲染 404 页面的问题。不过这一组件在 1.x 时就被移除了,你不得不多写若干行代码来解决这个问题。

    // 如果想要展示一个 404 页面(当前 URL 不变)
    <Route path='*' component={My404Component} />
    
    // 如果想要展示一个 404 页面(当前 URL 重定向到 /404 )
    <Route path='/404' component={My404Component} />  
    <Redirect from='*' to='/404' />  
    

    在 ReactRouter 4 中,你可以省点儿事直接用 <Miss> 组件。

    const App = () => (  
      <Router>
        <Match pattern="/foo"/>
        <Match pattern="/bar"/>
        <Miss component={NoMatch}/>
      </Router>
    )
    
    const NoMatch = ({ location }) => (  
      <div>Nothing matched {location.pathname}.</div>
    )
    

    ReactRouter 4 的大杀器:一个路由,多次匹配

    在上文中我们提到过,目前 ReactRouter 匹配到某个路由时,将直接渲染通过 component 定义的组件,并把命中的子路由对应的组件作为 this.props.children 传入。

    在前端 App 日益复杂的今天,一条路由的改变不仅仅简单的是页面的切换,甚至可能精细到页面上某些组件的切换。

    让我们直接看下面的代码:

    // 每条路由有两个组件,一个用于渲染 sidebar,一个用于渲染主页面
    const routes = [  
      { pattern: '/',
        exactly: true,
        sidebar: () => <div>Home!</div>,
        main: () => <h2>Main</h2>
      },
      { pattern: '/foo',
        sidebar: () => <div>foo!</div>,
        main: () => <h2>Foo</h2>
      },
      { pattern: '/bar',
        sidebar: () => <div>Bar!</div>,
        main: () => <h2>Bar</h2>
      }
    ]
    
    <Router history={history}>  
      <div className="page">
        <div className="sidebar">
          <ul>
            <li><Link to="/">Home</Link></li>
            <li><Link to="/foo">Foo</Link></li>
            <li><Link to="/bar">Bar</Link></li>
          </ul>
    
          /* 对当前路由进行匹配,并渲染侧边栏 */
          {routes.map((route, index) => (
            <Match
              key={index}
              pattern={route.pattern}
              component={route.sidebar}
              exactly={route.exactly}
            />
          ))}
        </div>
    
        <div className="main">
          /* 对当前路由进行匹配,并渲染主界面 */
          {routes.map((route, index) => (
            <Match
              key={index}
              pattern={route.pattern}
              component={route.main}
              exactly={route.exactly}
            />
          ))}
        </div>
      </div>
    </Router>  
    

    通过上面的代码片段我们可以看出,<Match> 的设计理念完全不同于 <Route>。使用 <Match>可以让我们在当前路由中尽情的匹配并渲染需要的组件,无论是需要渲染 Sidebar、BreadCrumb 还是主界面。

    若使用现有的 ReactRouter API,只能通过当前路由匹配主界面对应的组件,至于 Sidebar 和 BreadCrumb,只能传入当前的 pathname 手动进行匹配。由此可见 <Match> 将会为此类需求带来极大的便利。

    其他疑惑

    当然,还有几个大家普遍关心的问题官方文档中也有所提及:

    1. ReactRouter 的 API 是否还会有大的变化?

    答:只要 React 的 API 不变,这一版的 API 也不会变。

    2. 是否有对 Redux 的支持?

    答:将提供一个受控的 <ControlledRouter>,支持传入一个 location。(作者注:这下真的不需要 react-router-redux 了,撒花!)

    3. 新版是否对滚动位置管理添加支持?

    答:将会对 window 和独立组件的滚动位置提供管理功能。(作者注:目前在不添加额外配置的情况下,路由切换时并不会恢复滚动位置)

    ReactRouter 4 小结

    了解了这么多 ReactRouter 4 的内容,你是否喜欢新版的 API 设计呢?

    其实从 ReactRouter 4 的这些变动不难看出,ReactRouter 正在努力的朝纯声明式的 API 方向迈进,一方面减少不必要的命令式 API,一方面也提供更语义化的路由匹配方案。

    此外新的 ReactRouter 也提供了非常强大的动态路由能力,甚至对嵌套路由也有所支持,这也是一个复杂的前端应用所必须的功能。

    参考资料

    1. ReactRouter 4 文档
    2. ReactRouter 4 Github repo
    3. ReactRouter

    注:本文首发于我的个人博客 undefinedblog,欢迎大家捧个人场。

    又注:访问 reactchina.com 有惊喜

    Reactreact

    展开全文
  • react router4介绍

    2018-08-01 20:12:02
    React Router4是一个流行的纯React重写的包。现在的版本中已不需要路由配置,现在一切皆组件。 本文涵盖了开始使用React Router构建网站所需要的一切知识。我们将会为本地运动队制作一个网站。 代码 想看网站最终...

    React Router4是一个流行的纯React重写的包。现在的版本中已不需要路由配置,现在一切皆组件。

    本文涵盖了开始使用React Router构建网站所需要的一切知识。我们将会为本地运动队制作一个网站。

    代码

    想看网站最终效果,查看demo

    安装

    React Router被拆分成三个包:react-router,react-router-domreact-router-nativereact-router提供核心的路由组件与函数。其余两个则提供运行环境(即浏览器与react-native)所需的特定组件。

    进行网站(将会运行在浏览器环境中)构建,我们应当安装react-router-domreact-router-dom暴露出react-router中暴露的对象与方法,因此你只需要安装并引用react-router-dom即可。

    npm install --save react-router-dom
    

    路由器(Router)

    在你开始项目前,你需要决定你使用的路由器的类型。对于网页项目,存在<BrowserRouter><HashRouter>两种组件。当存在服务区来管理动态请求时,需要使用<BrowserRouter>组件,而<HashRouter>被用于静态网站。

    通常,我们更倾向选择<BrowserRouter>,但如果你的网站仅用来呈现静态文件,那么<HashRouter>将会是一个好选择。

    对于我们的项目,将设将会有服务器的动态支持,因此我们选择<BrowserRouter>作为路由器组件。

    历史(History)

    每个路由器都会创建一个history对象并用其保持追踪当前location[注1]并且在有变化时对网站进行重新渲染。这个history对象保证了React Router提供的其他组件的可用性,所以其他组件必须在router内部渲染。一个React Router组件如果向父级上追溯却找不到router组件,那么这个组件将无法正常工作。

    渲染<Router>

    路由器组件无法接受两个及以上的子元素。基于这种限制的存在,创建一个<App>组件来渲染应用其余部分是一个有效的方法(对于服务端渲染,将应用从router组件中分离也是重要的)。

    import { BrowserRouter } from 'react-router-dom'
    ReactDOM.render((
      <BrowserRouter>
        <App />
      </BrowserRouter>
    ), document.getElementById('root'))
    

    <App>

    应用通过<App>组件定义。简化一下,我们将应用拆分成两个部分。<Header>组件包含网站的导航链接。<Main>组件则呈现其余内容。

    // this component will be rendered by our <___Router>
    const App = () => (
      <div>
        <Header />
        <Main />
      </div>
    )
    

    注意:你可以按你喜欢的方式对应用布局,但是将路由与导航拆分出来对于这个入门教程会成家简单。

    路由(Route)

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

    路径(Path)

    <Route>接受一个数为string类型的path,该值路由匹配的路径名的类型。例如:<Route path='/roster'/>会匹配以/roster[注2]开头的路径名。在当前path参数与当前location的路径相匹配时,路由就会开始渲染React元素。若不匹配,路由不会进行任何操作[注3]。

    <Route path='/roster'/>
    // 当路径名为'/'时, path不匹配
    // 当路径名为'/roster'或'/roster/2'时, path匹配
    // 当你只想匹配'/roster'时,你需要使用"exact"参数
    // 则路由仅匹配'/roster'而不会匹配'/roster/2'
    <Route exact path='/roster'/>
    

    注意:在匹配路由时,React Router只关注location的路径名。当URL如下时:

    http://www.example.com/my-projects/one?extra=false
    

    React Router去匹配的只是'/my-projects/one'这一部分。

    匹配路径

    path-to-regexp包用来决定route元素的path参数与当前location是否匹配。它将路径字符串编译成正则表达式,并与当前location的路径名进行匹配比较。除了上面的例子外,路径字符串有更多高级的选项,详见[path-to-regexp文档]。
    当路由地址匹配成功后,会创建一个含有以下属性的match对象

    • url :与当前location路径名所匹配部分

    • path :路由的地址

    • isExact :path 是否等于 pathname

    • params :从path-to-regexp获取的路径中取出的值都被包含在这个对象中

    使用route tester这款工具来对路由与URL进行检验。

    注意:本例中路由路径仅支持绝对路径[注4]。

    创建你的路由

    可以在路由器(router)组件中的任意位置创建多个<Route>,但通常我们会把它们放在同一个位置。使用<Switch>组件来包裹一组<Route>。<Switch>会遍历自身的子元素(即路由)并对第一个匹配当前路径的元素进行渲染。

    对于本网站,我们希望匹配一下路径:

    • / : 主页

    • /roster : 团体列表

    • /roster/:number :运动员页面,使用运动员的编号作为标识

    • /schedule :团队的赛程表

    为了在应用中能匹配路径,在创建<Route>元素时必须带有需要匹配的path作为参数。

    <Switch>
      <Route exact path='/' component={Home}/>
      {/* both /roster and /roster/:number begin with /roster */}
      <Route path='/roster' component={Roster}/>
      <Route path='/schedule' component={Schedule}/>
    </Switch>
    

    <Route>是如何渲染的?

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

    • component : 一个React组件。当带有component参数的route匹配成功后,route会返回一个新的元素,其为component参数所对应的React组件(使用React.createElement创建)。

    • render : 一个返回React element的函数[注5]。当匹配成功后调用该函数。该过程与传入component参数类似,并且对于行级渲染与需要向元素传入额外参数的操作会更有用。

    • children : 一个返回React element的函数。与上述两个参数不同,无论route是否匹配当前location,其都会被渲染。

    <Route path='/page' component={Page} />
    const extraProps = { color: 'red' }
    <Route path='/page' render={(props) => (
      <Page {...props} data={extraProps}/>
    )}/>
    <Route path='/page' children={(props) => (
      props.match
        ? <Page {...props}/>
        : <EmptyPage {...props}/>
    )}/>
    

    通常component参数与render参数被更经常地使用。children参数偶尔会被使用,它更常用在path无法匹配时呈现的'空'状态。在本例中并不会有额外的状态,所以我们将使用<Route>的component参数。

    通过<Route>渲染的元素会被传入一些参数。分别是match对象,当前location对象[注6]以及history对象(由router创建)[注7]。

    <Main>

    现在我们清楚了根路由的结构,我们需要实际渲染我们的路由。对于这个应用,我们将会在<Main>组件中渲染<Switch>与<Route>,这一过程会将route匹配生成的HTML放在<main>节点中。

    import { Switch, Route } from 'react-router-dom'
    const Main = () => (
      <main>
        <Switch>
          <Route exact path='/' component={Home}/>
          <Route path='/roster' component={Roster}/>
          <Route path='/schedule' component={Schedule}/>
        </Switch>
      </main>
    )
    

    注意:主页路由包含额外参数。该参数用来保证路由能准确匹配path。

    嵌套路由

    运动员路由/roster/:number并未包含在上述<Switch>中。它由<Roster>组件负责在路径包含'/roster'的情形下进行渲染。

    在<Roster>组件中,我们将为两种路径进行渲染:

    • /roster :对应路径名仅仅是/roster时,因此需要在exact元素上添加exact参数。

    • /roster/:number : 该路由使用一个路由参数来获取/roster后的路径名。

      const Roster = () => (
      <Switch>

      <Route exact path='/roster' component={FullRoster}/>
      <Route path='/roster/:number' component={Player}/>

      </Switch>
      )

      组合在相同组件中分享共同前缀的路由是一种有用的方法。这就需要简化父路由并且提供一个区域来渲染具有相同前缀的通用路由。

    例如,<Roster>用来渲染所有以/roster开始的全部路由。

    const Roster = () => (
      <div>
        <h2>This is a roster page!</h2>
        <Switch>
          <Route exact path='/roster' component={FullRoster}/>
          <Route path='/roster/:number' component={Player}/>
        </Switch>
      </div>
    )
    

    路径参数

    有时路径名中存在我们需要获取的参数。例如,在运动员界面,我们需要获取运动员的编号。我们可以向route的路径字符串中添加path参数

    如'/roster/:number'中:number这种写法意味着/roster/后的路径名将会被获取并存在match.params.number中。例如,路径名'/roster/6'会获取到一个对象:

    { number: '6' } // 注获取的值是字符串类型的
    

    <Player>组件可以使用props.match.params对象来确定需要被渲染的运动员的数据。

    // 返回运动员对象的API
    import PlayerAPI from './PlayerAPI'
    const Player = (props) => {
      const player = PlayerAPI.get(
        parseInt(props.match.params.number, 10)
      )
      if (!player) {
        return <div>Sorry, but the player was not found</div>
      }
      return (
        <div>
          <h1>{player.name} (#{player.number})</h1>
          <h2>{player.position}</h2>
        </div>
    )
    

    你可以通过阅读path-to-regexp文档来了解更多。

    除了<Player>组件,我们的页面还包含<FullRoster>, <Schedule>以及 <Home>组件。

    const FullRoster = () => (
      <div>
        <ul>
          {
            PlayerAPI.all().map(p => (
              <li key={p.number}>
                <Link to={`/roster/${p.number}`}>{p.name}</Link>
              </li>
            ))
          }
        </ul>
      </div>
    )
    const Schedule = () => (
      <div>
        <ul>
          <li>6/5 @ Evergreens</li>
          <li>6/8 vs Kickers</li>
          <li>6/14 @ United</li>
        </ul>
      </div>
    )
    const Home = () => (
      <div>
        <h1>Welcome to the Tornadoes Website!</h1>
      </div>
    )
    

    Link

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

    import { Link } from 'react-router-dom'
    const Header = () => (
      <header>
        <nav>
          <ul>
            <li><Link to='/'>Home</Link></li>
            <li><Link to='/roster'>Roster</Link></li>
            <li><Link to='/schedule'>Schedule</Link></li>
          </ul>
        </nav>
      </header>
    )
    

    <Link>使用'to'参数来描述需要定位的页面。它的值即可是字符串也可是location对象(包含pathname,search,hash与state属性)。如果其值为字符床将会被转换为location对象。

    <Link to={{ pathname: '/roster/7' }}>Player #7</Link>
    

    注意:本例的link的pathname属性只能是绝对路径[注4]。

    例子

    一个完整的网站例子点击预览

    获取路由

    希望当下你已准备好深入构建你自己的网站了。

    我们已经了解了构建网站所需要的所有必须组件(<BrowserRouter>, <Route>, 以及 <Link>)。当然,还有一些我们没有涉及的组件。所幸React Router拥有优质的文档,你可以查看并从中了解更多的信息。文档也提供一系列的例子与源代码。

    注释:

    [1] locations 是一个含有描述URL不同部分属性的对象:

    // 一个基本的location对象
    { pathname: '/', search: '', hash: '', key: 'abc123' state: {} }
    

    [2] 你可以渲染无路径的<Route>,其将会匹配所有location。此法用于访问存在上下文中的变量与方法。

    [3] 如果你使用children参数,即便在当前location不匹配时route也将进行渲染。

    [4] 当需要支持相对路径的<Route>与<Link>时,你需要多做一些工作。相对<Link>将会比你之前看到的更为复杂。因其使用了父级的match对象而非当前URL来匹配相对路径。

    [5] 这是一个本质上无状态的函数组件。内部实现,component参数与render参数的组件是用很大的区别的。使用component参数的组件会使用React.createElement来创建元素,使用render参数的组件则会调用render函数。如果我们定义一个内联函数并将其传给component参数,这将会比使用render参数慢很多。

    <Route path='/one' component={One}/>
    // React.createElement(props.component)
    <Route path='/two' render={() => <Two />}/>
    // props.render()
    

    [6] <Route>与<Switch>组件都会带有location参数。这能让你使用与实际location不同的location去匹配地址。

    [7] 可以传入staticContext参数,不过这仅在服务端渲染时有用。

    展开全文
  • React fundamental 和 React Router
  • 本文主要介绍React Router定义路由之后如何传值,有关ReactReact Router 的基础请参考阮老师的博客注:本文示例React Router版本为:3.0.2,使用前请注意检查版本一.props.params官方例子使用React router定义...

    本文主要介绍React Router定义路由之后如何传值,有关React和React Router
    的基础请参考阮老师的博客

    注:本文示例React Router版本为:3.0.2,使用前请注意检查版本

    一.props.params

    官方例子使用React router定义路由时,我们可以给<Route>指定一个path,然后指定通配符可以携带参数到指定的path:
    首先定义路由到UserPage页面:

    import { Router,Route,hashHistory} from 'react-router';
    class App extends React.Component {
      render() {
        return (
            <Router history={hashHistory}>
                <Route path='/user/:name' component={UserPage}></Route>
            </Router>
        )
      }
    }

    上面指定参数一个参数name
    使用:

    import {Link,hashHistory} from 'react-router';

    1.Link组件实现跳转:

    <Link to="/user/sam">用户</Link>

    2.history跳转:

    hashHistory.push("/user/sam");

    当页面跳转到UserPage页面之后,取出传过来的值:

    export default class UserPage extends React.Component{
        constructor(props){
            super(props);
        }
        render(){
            return(<div>this.props.params.name</div>)
        }
    }

    上面的方法可以传递一个或多个值,但是每个值的类型都是字符串,没法传递一个对象,如果传递的话可以将json对象转换为字符串,然后传递过去,传递过去之后再将json字符串转换为对象将数据取出来
    如:定义路由:

    <Route path='/user/:data' component={UserPage}></Route>

    使用:

    var data = {id:3,name:sam,age:36};
    data = JSON.stringify(data);
    var path = `/user/${data}`;
    1.<Link to={path}>用户</Link>
    2.hashHistory.push(path);

    获取数据:

    var data = JSON.parse(this.props.params.data);
    var {id,name,age} = data;

    通过这种方式跳转到UserPage页面时只能通过传递字符串来传递参数,那么是否有其他方法来优雅地直接传递对象而不仅仅是字符串呢?

    二.query

    query方式使用很简单,类似于表单中的get方法,传递参数为明文:
    首先定义路由:

    <Route path='/user' component={UserPage}></Route>

    使用:

    var data = {id:3,name:sam,age:36};
    var path = {
      pathname:'/user',
      query:data,
    }
    1.<Link to={path}>用户</Link>
    2.hashHistory.push(path);

    获取数据:

    var data = this.props.location.query;
    var {id,name,age} = data;

    query方式可以传递任意类型的值,但是页面的URL也是由query的值拼接的,URL很长,那么有没有办法类似于表单post方式传递数据使得传递的数据不以明文传输呢?

    三.state

    state方式类似于post方式,使用方式和query类似,
    首先定义路由:

    <Route path='/user' component={UserPage}></Route>

    使用:

    var data = {id:3,name:sam,age:36};
    var path = {
      pathname:'/user',
      state:data,
    }
    1.<Link to={path}>用户</Link>
    2.hashHistory.push(path);

    获取数据:

    var data = this.props.location.state;
    var {id,name,age} = data;

    state方式依然可以传递任意类型的数据,而且可以不以明文方式传输。

    可以在实现后对比地址栏的URL来观察三种传值方式URL的区别

    展开全文
  • React Router 4 简易入门

    2018-05-17 11:41:50
    React Router4是一个流行的纯React重写的包。现在的版本中已不需要路由配置,现在一切皆组件。本文涵盖了开始使用React Router构建网站所需要的一切知识。我们将会为本地运动队制作一个网站。代码想看网站最终效果,...

    React Router4是一个流行的纯React重写的包。现在的版本中已不需要路由配置,现在一切皆组件。

    本文涵盖了开始使用React Router构建网站所需要的一切知识。我们将会为本地运动队制作一个网站。

    代码

    想看网站最终效果,查看demo点击预览

    安装

    React Router被拆分成三个包:react-router,react-router-domreact-router-nativereact-router提供核心的路由组件与函数。其余两个则提供运行环境(即浏览器与react-native)所需的特定组件。

    进行网站(将会运行在浏览器环境中)构建,我们应当安装react-router-domreact-router-dom暴露出react-router中暴露的对象与方法,因此你只需要安装并引用react-router-dom即可。

    npm install --save react-router-dom
    

    路由器(Router)

    在你开始项目前,你需要决定你使用的路由器的类型。对于网页项目,存在<BrowserRouter><HashRouter>两种组件。当存在服务区来管理动态请求时,需要使用<BrowserRouter>组件,而<HashRouter>被用于静态网站。

    通常,我们更倾向选择<BrowserRouter>,但如果你的网站仅用来呈现静态文件,那么<HashRouter>将会是一个好选择。

    对于我们的项目,将设将会有服务器的动态支持,因此我们选择<BrowserRouter>作为路由器组件。

    历史(History)

    每个路由器都会创建一个history对象并用其保持追踪当前location[注1]并且在有变化时对网站进行重新渲染。这个history对象保证了React Router提供的其他组件的可用性,所以其他组件必须在router内部渲染。一个React Router组件如果向父级上追溯却找不到router组件,那么这个组件将无法正常工作。

    渲染<Router>

    路由器组件无法接受两个及以上的子元素。基于这种限制的存在,创建一个<App>组件来渲染应用其余部分是一个有效的方法(对于服务端渲染,将应用从router组件中分离也是重要的)。

    import { BrowserRouter } from 'react-router-dom'
    ReactDOM.render((
      <BrowserRouter>
        <App />
      </BrowserRouter>
    ), document.getElementById('root'))
    

    <App>

    应用通过<App>组件定义。简化一下,我们将应用拆分成两个部分。<Header>组件包含网站的导航链接。<Main>组件则呈现其余内容。

    // this component will be rendered by our <___Router>
    const App = () => (
      <div>
        <Header />
        <Main />
      </div>
    )
    

    注意:你可以按你喜欢的方式对应用布局,但是将路由与导航拆分出来对于这个入门教程会成家简单。

    路由(Route)

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

    路径(Path)

    <Route>接受一个数为string类型的path,该值路由匹配的路径名的类型。例如:<Route path='/roster'/>会匹配以/roster[注2]开头的路径名。在当前path参数与当前location的路径相匹配时,路由就会开始渲染React元素。若不匹配,路由不会进行任何操作[注3]。

    <Route path='/roster'/>
    // 当路径名为'/'时, path不匹配
    // 当路径名为'/roster''/roster/2'时, path匹配
    // 当你只想匹配'/roster'时,你需要使用"exact"参数
    // 则路由仅匹配'/roster'而不会匹配'/roster/2'
    <Route exact path='/roster'/>
    

    注意:在匹配路由时,React Router只关注location的路径名。当URL如下时:

    http://www.example.com/my-projects/one?extra=false
    

    React Router去匹配的只是'/my-projects/one'这一部分。

    匹配路径

    path-to-regexp包用来决定route元素的path参数与当前location是否匹配。它将路径字符串编译成正则表达式,并与当前location的路径名进行匹配比较。除了上面的例子外,路径字符串有更多高级的选项,详见[path-to-regexp文档]。
    当路由地址匹配成功后,会创建一个含有以下属性的match对象

    • url :与当前location路径名所匹配部分

    • path :路由的地址

    • isExact :path 是否等于 pathname

    • params :从path-to-regexp获取的路径中取出的值都被包含在这个对象中

    使用route tester这款工具来对路由与URL进行检验。

    注意:本例中路由路径仅支持绝对路径[注4]。

    创建你的路由

    可以在路由器(router)组件中的任意位置创建多个<Route>,但通常我们会把它们放在同一个位置。使用<Switch>组件来包裹一组<Route>。<Switch>会遍历自身的子元素(即路由)并对第一个匹配当前路径的元素进行渲染。

    对于本网站,我们希望匹配一下路径:

    • / : 主页

    • /roster : 团体列表

    • /roster/:number :运动员页面,使用运动员的编号作为标识

    • /schedule :团队的赛程表

    为了在应用中能匹配路径,在创建<Route>元素时必须带有需要匹配的path作为参数。

    <Switch>
      <Route exact path='/' component={Home}/>
      {/* both /roster and /roster/:number begin with /roster */}
      <Route path='/roster' component={Roster}/>
      <Route path='/schedule' component={Schedule}/>
    </Switch>
    

    <Route>是如何渲染的?

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

    • component : 一个React组件。当带有component参数的route匹配成功后,route会返回一个新的元素,其为component参数所对应的React组件(使用React.createElement创建)。

    • render : 一个返回React element的函数[注5]。当匹配成功后调用该函数。该过程与传入component参数类似,并且对于行级渲染与需要向元素传入额外参数的操作会更有用。

    • children : 一个返回React element的函数。与上述两个参数不同,无论route是否匹配当前location,其都会被渲染。

    <Route path='/page' component={Page} />
    const extraProps = { color: 'red' }
    <Route path='/page' render={(props) => (
      <Page {...props} data={extraProps}/>
    )}/>
    <Route path='/page' children={(props) => (
      props.match
        ? <Page {...props}/>
        : <EmptyPage {...props}/>
    )}/>
    

    通常component参数与render参数被更经常地使用。children参数偶尔会被使用,它更常用在path无法匹配时呈现的'空'状态。在本例中并不会有额外的状态,所以我们将使用<Route>的component参数。

    通过<Route>渲染的元素会被传入一些参数。分别是match对象,当前location对象[注6]以及history对象(由router创建)[注7]。

    <Main>

    现在我们清楚了根路由的结构,我们需要实际渲染我们的路由。对于这个应用,我们将会在<Main>组件中渲染<Switch>与<Route>,这一过程会将route匹配生成的HTML放在<main>节点中。

    import { Switch, Route } from 'react-router-dom'
    const Main = () => (
      <main>
        <Switch>
          <Route exact path='/' component={Home}/>
          <Route path='/roster' component={Roster}/>
          <Route path='/schedule' component={Schedule}/>
        </Switch>
      </main>
    )
    

    注意:主页路由包含额外参数。该参数用来保证路由能准确匹配path。

    嵌套路由

    运动员路由/roster/:number并未包含在上述<Switch>中。它由<Roster>组件负责在路径包含'/roster'的情形下进行渲染。

    在<Roster>组件中,我们将为两种路径进行渲染:

    • /roster :对应路径名仅仅是/roster时,因此需要在exact元素上添加exact参数。

    • /roster/:number : 该路由使用一个路由参数来获取/roster后的路径名。

      const Roster = () => (
      <Switch>

      <Route exact path='/roster' component={FullRoster}/>
      <Route path='/roster/:number' component={Player}/>

      </Switch>
      )

      组合在相同组件中分享共同前缀的路由是一种有用的方法。这就需要简化父路由并且提供一个区域来渲染具有相同前缀的通用路由。

    例如,<Roster>用来渲染所有以/roster开始的全部路由。

    const Roster = () => (
      <div>
        <h2>This is a roster page!</h2>
        <Switch>
          <Route exact path='/roster' component={FullRoster}/>
          <Route path='/roster/:number' component={Player}/>
        </Switch>
      </div>
    )
    

    路径参数

    有时路径名中存在我们需要获取的参数。例如,在运动员界面,我们需要获取运动员的编号。我们可以向route的路径字符串中添加path参数

    如'/roster/:number'中:number这种写法意味着/roster/后的路径名将会被获取并存在match.params.number中。例如,路径名'/roster/6'会获取到一个对象:

    { number: '6' } // 注获取的值是字符串类型的
    

    <Player>组件可以使用props.match.params对象来确定需要被渲染的运动员的数据。

    // 返回运动员对象的API
    import PlayerAPI from './PlayerAPI'
    const Player = (props) => {
      const player = PlayerAPI.get(
        parseInt(props.match.params.number, 10)
      )
      if (!player) {
        return <div>Sorry, but the player was not found</div>
      }
      return (
        <div>
          <h1>{player.name} (#{player.number})</h1>
          <h2>{player.position}</h2>
        </div>
    )
    

    你可以通过阅读path-to-regexp文档来了解更多。

    除了<Player>组件,我们的页面还包含<FullRoster>, <Schedule>以及 <Home>组件。

    const FullRoster = () => (
      <div>
        <ul>
          {
            PlayerAPI.all().map(p => (
              <li key={p.number}>
                <Link to={`/roster/${p.number}`}>{p.name}</Link>
              </li>
            ))
          }
        </ul>
      </div>
    )
    const Schedule = () => (
      <div>
        <ul>
          <li>6/5 @ Evergreens</li>
          <li>6/8 vs Kickers</li>
          <li>6/14 @ United</li>
        </ul>
      </div>
    )
    const Home = () => (
      <div>
        <h1>Welcome to the Tornadoes Website!</h1>
      </div>
    )
    

    Link

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

    import { Link } from 'react-router-dom'
    const Header = () => (
      <header>
        <nav>
          <ul>
            <li><Link to='/'>Home</Link></li>
            <li><Link to='/roster'>Roster</Link></li>
            <li><Link to='/schedule'>Schedule</Link></li>
          </ul>
        </nav>
      </header>
    )
    

    <Link>使用'to'参数来描述需要定位的页面。它的值即可是字符串也可是location对象(包含pathname,search,hash与state属性)。如果其值为字符床将会被转换为location对象。

    <Link to={{ pathname: '/roster/7' }}>Player #7</Link>
    

    注意:本例的link的pathname属性只能是绝对路径[注4]。

    例子

    一个完整的网站例子

    获取路由

    希望当下你已准备好深入构建你自己的网站了。

    我们已经了解了构建网站所需要的所有必须组件(<BrowserRouter>, <Route>, 以及 <Link>)。当然,还有一些我们没有涉及的组件。所幸React Router拥有优质的文档,你可以查看并从中了解更多的信息。文档也提供一系列的例子与源代码。

    注释:

    [1] locations 是一个含有描述URL不同部分属性的对象:

    // 一个基本的location对象
    { pathname: '/', search: '', hash: '', key: 'abc123' state: {} }
    

    [2] 你可以渲染无路径的<Route>,其将会匹配所有location。此法用于访问存在上下文中的变量与方法。

    [3] 如果你使用children参数,即便在当前location不匹配时route也将进行渲染。

    [4] 当需要支持相对路径的<Route>与<Link>时,你需要多做一些工作。相对<Link>将会比你之前看到的更为复杂。因其使用了父级的match对象而非当前URL来匹配相对路径。

    [5] 这是一个本质上无状态的函数组件。内部实现,component参数与render参数的组件是用很大的区别的。使用component参数的组件会使用React.createElement来创建元素,使用render参数的组件则会调用render函数。如果我们定义一个内联函数并将其传给component参数,这将会比使用render参数慢很多。

    <Route path='/one' component={One}/>
    // React.createElement(props.component)
    <Route path='/two' render={() => <Two />}/>
    // props.render()
    

    [6] <Route>与<Switch>组件都会带有location参数。这能让你使用与实际location不同的location去匹配地址。

    [7] 可以传入staticContext参数,不过这仅在服务端渲染时有用。

    展开全文
  • react router 配置404页面

    2019-07-18 01:37:46
    使用Vue相关的技术栈2年左右了,在路由管理上一直用的比较得心应手,现在的项目使用react开发,路由自然也就切换到了react router,所用版本为react router 4 在Vue router配置中,我们可以很简单的配置出404页面 ...
  • React Router4

    2019-06-15 14:09:09
    React Router4是一个流行的纯React重写的包。现在的版本中已不需要路由配置,现在一切皆组件。 本文涵盖了开始使用React Router构建网站所需要的一切知识。我们将会为本地运动队制作一个网站。 代码 想看网站最终...
  • 初探 React Router 4.0

    2017-04-04 22:46:09
    React Router 4.0 (以下简称 RR4) 已经正式发布,它遵循React的设计理念,即万物皆组件。所以 RR4 只是一堆 提供了导航功能的组件(还有若干对象和方法),具有声明式(引入即用),可组合性的特点。...
  • React Router 4 发布,我能清晰地感觉到来自 Twitter 大家对新版本中其 大量的修改 的不同声音。诚然,我在学习 React Router 4 的第一天,也是非常痛苦的,但是,这并不是因为看它的 API,而是反复思考使用它的模式...
  • React Router v4 入坑指南

    2018-11-19 10:25:13
    万恶的根源 距离React Router v4 正式发布也已经过去三个月了,这周把一个...(ヾ(。ꏿ﹏ꏿ)ノ゙咦,此刻相信机智如我的你也会发现,ReactRouter v3 去哪儿了?整丢了??巴拉出锅了???敢不敢给我个完美的解释!...
  • 本博文提供一个单网页结构网页(SPA)使用React Router路由控制跳转的完整例子。 关于配置可以查看我之前的一篇博客:[一步一步进入React的世界(React+Webpack+ES6组合配置)]
  • React router 4.x

    2019-05-10 23:32:15
    React router 在gitHub上,学会找官方文档,看文档 安装 npm install react-router-dom --save 导入模块 import { BrowserRouter as Router, Route,Link } from &amp;amp;amp;amp;quot;react-router-dom&...
  • 转载自:react-routerreact-router-dom的区别react-router-v4,我称之为“第四代react-router”,react-routerreact-router-dom的区别是什么呢?为什么有时候我们看到如下的写法:写法1:import {Swtich, Route, ...
  • 参考文档: react router 文档 import React from "react" import { withRouter } from "react-router-dom" class ShowTheLocation extends React.Component { toOtherRoute = () => { const urlObj = { ....
  • React-router 4路由监听

    2019-06-10 12:33:07
    React Router4是一个纯React重写的包,现在的版本中已不需要路由配置,一切皆组件。 问题出发点 最近在一个新的H5项目中使用了react router 4 ("react-router-dom": "^4.2.2"),项目中的一部分页面是需要给app客户端...
  • React - Router4

    2018-05-04 14:00:09
    安装React Router被拆分成三个包:react-router,react-router-dom和react-router-native。react-router提供核心的路由组件与函数。其余两个则提供运行环境(即浏览器与react-native)所需的特定组件。进行网站(将会...
  • React Router简单Demo

    2019-07-09 20:44:41
    react router包含react-router,react-router-dom和react-router-native这三个包,分别是路由核心组件和浏览器端组件和native端组件,所以我们需要安装react-router-dom npm install --save react-router-dom 安装后...
  • React-router4的简单理解

    2018-07-30 17:29:21
     react-router4React官方推挤路由库,4是最新版本。和之前版本不兼容,浏览器和RN均兼容React Router 4.0 (以下简称 RR4) 已经正式发布,它遵循React的设计理念,即万物皆组件。所以 RR4 只是一堆 提供了导航...
  • React Router Config 简介 React Router Config 是 React Router 的一个辅助工具,主要帮你做集中配置式路由 什么是配置式路由呢,如下 import App from '../App'; import Child from '../components/route-static/...
1 2 3 4 5 ... 20
收藏数 22,118
精华内容 8,847
关键字:

4 react router