React Router 使用教程

作者: 阮一峰

日期: 2016年5月25日

真正学会 React 是一个漫长的过程。

你会发现,它不是一个库,也不是一个框架,而是一个庞大的体系。想要发挥它的威力,整个技术栈都要配合它改造。你要学习一整套解决方案,从后端到前端,都是全新的做法。

举例来说,React 不使用 HTML,而使用 JSX 。它打算抛弃 DOM,要求开发者不要使用任何 DOM 方法。它甚至还抛弃了 SQL ,自己发明了一套查询语言 GraphQL 。当然,这些你都可以不用,React 照样运行,但是就发挥不出它的最大威力。

这样说吧,你只要用了 React,就会发现合理的选择就是,采用它的整个技术栈。

本文介绍 React 体系的一个重要部分:路由库React-Router。它是官方维护的,事实上也是唯一可选的路由库。它通过管理 URL,实现组件的切换和状态的变化,开发复杂的应用几乎肯定会用到。

本文针对初学者,尽量写得简洁易懂。预备知识是 React 的基本用法,可以参考我写的《React 入门实例教程》

另外,我没有准备示例库,因为官方的示例库非常棒,由浅入深,分成14步,每一步都有详细的代码解释。我强烈建议你先跟着做一遍,然后再看下面的API讲解。

([说明] 本文写作时,React-router 是 2.x 版,本文的内容只适合这个版本,与最新的 4.x 版不兼容。目前,官方同时维护 2.x 和 4.x 两个版本,所以前者依然可以用在项目中。2017年3月)

一、基本用法

React Router 安装命令如下。


$ npm install -S react-router

使用时,路由器Router就是React的一个组件。


import { Router } from 'react-router';
render(<Router/>, document.getElementById('app'));

Router组件本身只是一个容器,真正的路由要通过Route组件定义。


import { Router, Route, hashHistory } from 'react-router';

render((
  <Router history={hashHistory}>
    <Route path="/" component={App}/>
  </Router>
), document.getElementById('app'));

上面代码中,用户访问根路由/(比如http://www.example.com/),组件APP就会加载到document.getElementById('app')

你可能还注意到,Router组件有一个参数history,它的值hashHistory表示,路由的切换由URL的hash变化决定,即URL的#部分发生变化。举例来说,用户访问http://www.example.com/,实际会看到的是http://www.example.com/#/

Route组件定义了URL路径与组件的对应关系。你可以同时使用多个Route组件。


<Router history={hashHistory}>
  <Route path="/" component={App}/>
  <Route path="/repos" component={Repos}/>
  <Route path="/about" component={About}/>
</Router>

上面代码中,用户访问/repos(比如http://localhost:8080/#/repos)时,加载Repos组件;访问/abouthttp://localhost:8080/#/about)时,加载About组件。

二、嵌套路由

Route组件还可以嵌套。


<Router history={hashHistory}>
  <Route path="/" component={App}>
    <Route path="/repos" component={Repos}/>
    <Route path="/about" component={About}/>
  </Route>
</Router>

上面代码中,用户访问/repos时,会先加载App组件,然后在它的内部再加载Repos组件。


<App>
  <Repos/>
</App>

App组件要写成下面的样子。


export default React.createClass({
  render() {
    return <div>
      {this.props.children}
    </div>
  }
})

上面代码中,App组件的this.props.children属性就是子组件。

子路由也可以不写在Router组件里面,单独传入Router组件的routes属性。


let routes = <Route path="/" component={App}>
  <Route path="/repos" component={Repos}/>
  <Route path="/about" component={About}/>
</Route>;

<Router routes={routes} history={browserHistory}/>

三、 path 属性

Route组件的path属性指定路由的匹配规则。这个属性是可以省略的,这样的话,不管路径是否匹配,总是会加载指定组件。

请看下面的例子。


<Route path="inbox" component={Inbox}>
   <Route path="messages/:id" component={Message} />
</Route>

上面代码中,当用户访问/inbox/messages/:id时,会加载下面的组件。


<Inbox>
  <Message/>
</Inbox>

如果省略外层Routepath参数,写成下面的样子。


<Route component={Inbox}>
  <Route path="inbox/messages/:id" component={Message} />
</Route>

现在用户访问/inbox/messages/:id时,组件加载还是原来的样子。


<Inbox>
  <Message/>
</Inbox>

四、通配符

path属性可以使用通配符。


<Route path="/hello/:name">
// 匹配 /hello/michael
// 匹配 /hello/ryan

<Route path="/hello(/:name)">
// 匹配 /hello
// 匹配 /hello/michael
// 匹配 /hello/ryan

<Route path="/files/*.*">
// 匹配 /files/hello.jpg
// 匹配 /files/hello.html

<Route path="/files/*">
// 匹配 /files/ 
// 匹配 /files/a
// 匹配 /files/a/b

<Route path="/**/*.jpg">
// 匹配 /files/hello.jpg
// 匹配 /files/path/to/file.jpg

通配符的规则如下。

(1):paramName

:paramName匹配URL的一个部分,直到遇到下一个/?#为止。这个路径参数可以通过this.props.params.paramName取出。

(2)()

()表示URL的这个部分是可选的。

(3)*

*匹配任意字符,直到模式里面的下一个字符为止。匹配方式是非贪婪模式。

(4) **

** 匹配任意字符,直到下一个/?#为止。匹配方式是贪婪模式。

path属性也可以使用相对路径(不以/开头),匹配时就会相对于父组件的路径,可以参考上一节的例子。嵌套路由如果想摆脱这个规则,可以使用绝对路由。

路由匹配规则是从上到下执行,一旦发现匹配,就不再其余的规则了。


<Route path="/comments" ... />
<Route path="/comments" ... />

上面代码中,路径/comments同时匹配两个规则,第二个规则不会生效。

设置路径参数时,需要特别小心这一点。


<Router>
  <Route path="/:userName/:id" component={UserPage}/>
  <Route path="/about/me" component={About}/>
</Router>

上面代码中,用户访问/about/me时,不会触发第二个路由规则,因为它会匹配/:userName/:id这个规则。因此,带参数的路径一般要写在路由规则的底部。

此外,URL的查询字符串/foo?bar=baz,可以用this.props.location.query.bar获取。

五、IndexRoute 组件

下面的例子,你会不会觉得有一点问题?


<Router>
  <Route path="/" component={App}>
    <Route path="accounts" component={Accounts}/>
    <Route path="statements" component={Statements}/>
  </Route>
</Router>

上面代码中,访问根路径/,不会加载任何子组件。也就是说,App组件的this.props.children,这时是undefined

因此,通常会采用{this.props.children || <Home/>}这样的写法。这时,Home明明是AccountsStatements的同级组件,却没有写在Route中。

IndexRoute就是解决这个问题,显式指定Home是根路由的子组件,即指定默认情况下加载的子组件。你可以把IndexRoute想象成某个路径的index.html


<Router>
  <Route path="/" component={App}>
    <IndexRoute component={Home}/>
    <Route path="accounts" component={Accounts}/>
    <Route path="statements" component={Statements}/>
  </Route>
</Router>

现在,用户访问/的时候,加载的组件结构如下。


<App>
  <Home/>
</App>

这种组件结构就很清晰了:App只包含下级组件的共有元素,本身的展示内容则由Home组件定义。这样有利于代码分离,也有利于使用React Router提供的各种API。

注意,IndexRoute组件没有路径参数path

六、Redirect 组件

<Redirect>组件用于路由的跳转,即用户访问一个路由,会自动跳转到另一个路由。


<Route path="inbox" component={Inbox}>
  {/* 从 /inbox/messages/:id 跳转到 /messages/:id */}
  <Redirect from="messages/:id" to="/messages/:id" />
</Route>

现在访问/inbox/messages/5,会自动跳转到/messages/5

七、IndexRedirect 组件

IndexRedirect组件用于访问根路由的时候,将用户重定向到某个子组件。


<Route path="/" component={App}>
  <IndexRedirect to="/welcome" />
  <Route path="welcome" component={Welcome} />
  <Route path="about" component={About} />
</Route>

上面代码中,用户访问根路径时,将自动重定向到子组件welcome

八、Link

Link组件用于取代<a>元素,生成一个链接,允许用户点击后跳转到另一个路由。它基本上就是<a>元素的React 版本,可以接收Router的状态。


render() {
  return <div>
    <ul role="nav">
      <li><Link to="/about">About</Link></li>
      <li><Link to="/repos">Repos</Link></li>
    </ul>
  </div>
}

如果希望当前的路由与其他路由有不同样式,这时可以使用Link组件的activeStyle属性。


<Link to="/about" activeStyle={{color: 'red'}}>About</Link>
<Link to="/repos" activeStyle={{color: 'red'}}>Repos</Link>

上面代码中,当前页面的链接会红色显示。

另一种做法是,使用activeClassName指定当前路由的Class


<Link to="/about" activeClassName="active">About</Link>
<Link to="/repos" activeClassName="active">Repos</Link>

上面代码中,当前页面的链接的class会包含active

Router组件之外,导航到路由页面,可以使用浏览器的History API,像下面这样写。


import { browserHistory } from 'react-router';
browserHistory.push('/some/path');

九、IndexLink

如果链接到根路由/,不要使用Link组件,而要使用IndexLink组件。

这是因为对于根路由来说,activeStyleactiveClassName会失效,或者说总是生效,因为/会匹配任何子路由。而IndexLink组件会使用路径的精确匹配。


<IndexLink to="/" activeClassName="active">
  Home
</IndexLink>

上面代码中,根路由只会在精确匹配时,才具有activeClassName

另一种方法是使用Link组件的onlyActiveOnIndex属性,也能达到同样效果。


<Link to="/" activeClassName="active" onlyActiveOnIndex={true}>
  Home
</Link>

实际上,IndexLink就是对Link组件的onlyActiveOnIndex属性的包装。

十、histroy 属性

Router组件的history属性,用来监听浏览器地址栏的变化,并将URL解析成一个地址对象,供 React Router 匹配。

history属性,一共可以设置三种值。

  • browserHistory
  • hashHistory
  • createMemoryHistory

如果设为hashHistory,路由将通过URL的hash部分(#)切换,URL的形式类似example.com/#/some/path


import { hashHistory } from 'react-router'

render(
  <Router history={hashHistory} routes={routes} />,
  document.getElementById('app')
)

如果设为browserHistory,浏览器的路由就不再通过Hash完成了,而显示正常的路径example.com/some/path,背后调用的是浏览器的History API。


import { browserHistory } from 'react-router'

render(
  <Router history={browserHistory} routes={routes} />,
  document.getElementById('app')
)

但是,这种情况需要对服务器改造。否则用户直接向服务器请求某个子路由,会显示网页找不到的404错误。

如果开发服务器使用的是webpack-dev-server,加上--history-api-fallback参数就可以了。


$ webpack-dev-server --inline --content-base . --history-api-fallback

createMemoryHistory主要用于服务器渲染。它创建一个内存中的history对象,不与浏览器URL互动。


const history = createMemoryHistory(location)

十一、表单处理

Link组件用于正常的用户点击跳转,但是有时还需要表单跳转、点击按钮跳转等操作。这些情况怎么跟React Router对接呢?

下面是一个表单。


<form onSubmit={this.handleSubmit}>
  <input type="text" placeholder="userName"/>
  <input type="text" placeholder="repo"/>
  <button type="submit">Go</button>
</form>

第一种方法是使用browserHistory.push


import { browserHistory } from 'react-router'

// ...
  handleSubmit(event) {
    event.preventDefault()
    const userName = event.target.elements[0].value
    const repo = event.target.elements[1].value
    const path = `/repos/${userName}/${repo}`
    browserHistory.push(path)
  },

第二种方法是使用context对象。


export default React.createClass({

  // ask for `router` from context
  contextTypes: {
    router: React.PropTypes.object
  },

  handleSubmit(event) {
    // ...
    this.context.router.push(path)
  },
})

十二、路由的钩子

每个路由都有EnterLeave钩子,用户进入或离开该路由时触发。


<Route path="about" component={About} />
<Route path="inbox" component={Inbox}>
  <Redirect from="messages/:id" to="/messages/:id" />
</Route>

上面的代码中,如果用户离开/messages/:id,进入/about时,会依次触发以下的钩子。

  • /messages/:idonLeave
  • /inboxonLeave
  • /aboutonEnter

下面是一个例子,使用onEnter钩子替代<Redirect>组件。


<Route path="inbox" component={Inbox}>
  <Route
    path="messages/:id"
    onEnter={
      ({params}, replace) => replace(`/messages/${params.id}`)
    } 
  />
</Route>

onEnter钩子还可以用来做认证。


const requireAuth = (nextState, replace) => {
    if (!auth.isAdmin()) {
        // Redirect to Home page if not an Admin
        replace({ pathname: '/' })
    }
}
export const AdminRoutes = () => {
  return (
     <Route path="/admin" component={Admin} onEnter={requireAuth} />
  )
}

下面是一个高级应用,当用户离开一个路径的时候,跳出一个提示框,要求用户确认是否离开。


const Home = withRouter(
  React.createClass({
    componentDidMount() {
      this.props.router.setRouteLeaveHook(
        this.props.route, 
        this.routerWillLeave
      )
    },

    routerWillLeave(nextLocation) {
      // 返回 false 会继续停留当前页面,
      // 否则,返回一个字符串,会显示给用户,让其自己决定
      if (!this.state.isSaved)
        return '确认要离开?';
    },
  })
)

上面代码中,setRouteLeaveHook方法为Leave钩子指定routerWillLeave函数。该方法如果返回false,将阻止路由的切换,否则就返回一个字符串,提示用户决定是否要切换。

(完)

留言(126条)

非常不错,简洁、清楚,阮大侠的笔锋越来越高大上。

嵌套路由下这段代码有点小问题

@童奇:

谢谢指出,改过缩进了。

6,7,12部分的代码转义有问题,

@胡子拉碴:

解析引擎有点问题,暂时先用全角符号代替.

非常感谢老师的分享,受益匪浅~

兼容性如何

React 全家桶。 哈哈

React Router 版本更新的很快

老师目前讲解的是对哪个版本呢

在 2.4.0以上版本 ,js 点击事件 的路由跳转 变化很大呀

到现在还不知道react的威力强大在哪里? 而且感觉还更复杂,因为几乎要全部新学所有东西。可能没有接触过大数据量的场景,总之写了3,4个月了,只是感觉到它的复杂,在我看来其它框架遇到的问题,react,redux也不能完全解决,反而是增加了一种学习成本。最怀疑的,react这种火热还会持续多久?

想问下阮老师,对于想写nodejs(API)的职业规划有何建议?另外,koa和expressjs哪个比较稳定?看了一下网络上对koa的介绍和评价,虽然有些(也许)是es未来趋势的新特性,但是我心底里比较抵触es的新特性(除非它们事实上已经成为标准,并且至少有2-3年的存活历史,而不需要再依赖polyfill)。expressjs看起来有些年头,而且大致看了下它的api也比较简单。但是犹豫的是,如果后续换单位,是不是行业内更多的是已经使用koa?或还是其它框架?

谢谢!

React 看起来要颠覆前端啊

期待一下 redux

您好,我想请教您作为一个前端菜鸟,应该怎样去学习呢?我一直想学点东西,但是每次在学习的过程中遇到一些陌生的框架或者库什么的,就想着又去学那个,所以每次都是半途而废,好纠结啊

引用奕佚的发言:

您好,我想请教您作为一个前端菜鸟,应该怎样去学习呢?我一直想学点东西,但是每次在学习的过程中遇到一些陌生的框架或者库什么的,就想着又去学那个,所以每次都是半途而废,好纠结啊

我建议你以“面向功能实现”的思路去学习。什么意思?就是学习的目的是实现功能,学习的目的不是学会某个技术。我写了一篇文章,希望对你有帮助:)

http://dwz.cn/3tbxyS

一直很喜欢老师的文章,希望能写一个Redux的教程,以及React+React Router+Redux结合的教程。非常感谢!

进来学习的,同时给老师赞一个!

一直追随阮老师的脚步。。

react 还是 angular2....

在react的门口徘徊半年了,还没进去,( ▼-▼ )

apache服务器的.htaccess照着官方给的方案改,完全不起作用啊,搞得我只能用hashHistory,有没有遇到类似问题的朋友啊

阮老师好,示例库第十一节,在Windows环境下使用SET NODE_ENV=production npm start 不起作用,老师有没有遇到这个问题?

最后一个“当用户离开一个路径的时候,跳出一个提示框”下边的代码写错了“this.props.router.setRouteLeaveHook” 应该是“this.context.router.setRouteLeaveHook”
即props应该改为是context

引用Mark的发言:

阮老师好,示例库第十一节,在Windows环境下使用SET NODE_ENV=production npm start 不起作用,老师有没有遇到这个问题?

在window环境下命令窗口里应该如下使用: 这个应该先执行 set node_env=production 然后在执行 npm start 而不是一整行一次执行。这样就起作用了,你可以试试

@如理

What makes you feel React is nothing but more complicated? The most stand out is its performance, this is well know. But sides this, it's so easy to write, especially it comes up with other frameworks. Just one example, if you use React + Relay + GraphQL, it is declarative instead of imperative -- so it handles all the async rendering for you, make your application fast and easy to develop.

谢谢阮老师的分享,又学到了新知识,重新过了遍react-router的官方DEMO,确实浅显易懂。
很喜欢这一期的配图!

阮老师 你是我这种野路子的信仰!

引用zhaoqize的发言:

阮老师 你是我这种野路子的信仰!

+1

引用eric的发言:

期待一下 redux

期待redux

引用liko的发言:

apache服务器的.htaccess照着官方给的方案改,完全不起作用啊,搞得我只能用hashHistory,有没有遇到类似问题的朋友啊

同样被这个问题困惑,nginx 上面配置不成功!只能退回hashHistory

阮老师,请教下如何去除去是URL中的?_k参数?

引用经年的发言:

期待redux

期待

问一下老师,如果require.ensure异步加载js文件,客户端点击url显示ok,异步能加载进来,但是如果直接访问该地址就会出现错误,如果是同步加载,完全没问题。

刚入们小白学习react求解答:
router的嵌套使用没有效果啊,

<Route path="/" component={App}>
<Route path="/demo" component={demo}/>
</Route>

我定义了两个组件app和haha,让他们返回app和demo,
然后我输入了/demo这个url,却没有渲染demo,只有一个app

真心期待Redux!!!!!!!!

"当用户离开一个路径的时候,跳出一个提示框,要求用户确认是否离开"这个案例里面,this.props.router错误,应该是this.context.router

@Airma:

我出现了同样的问题,求问一下,百度没有找到方法

引用Airma的发言:

刚入们小白学习react求解答:
router的嵌套使用没有效果啊,

<Route path="/" component={App}>
<Route path="/demo" component={demo}/>
</Route>

我定义了两个组件app和haha,让他们返回app和demo,
然后我输入了/demo这个url,却没有渲染demo,只有一个app

嵌套里面的"/demo"应该是不需要"/"的,"path=demo"就可以了吧.

大家使用 import {Router,Route,Link} from 'react-router';这种写法,在浏览器中打开难道没遇到 require not defined的报错消息吗?

replace 钩子函数那 not a function 输出是 无定义

还是阮司机的教程给力……关于在方法中处理跳转问题,死活没想到用HistoryAPI……

写的不错,言简意赅。学到了东西,比起那些讲废话的视频教程确实不错

很有用 看了几个 还是阮老师写的最明白

您好,使用 browserHistory 时碰到个问题,路由的跳转是匹配根目录而不是项目目录。

例如目录为 localhost/login 正常,但目录为 http://localhost/path/login 就会报错了。

可以通过 useRouterHistory 定义 router 的根目录,但这样岂不是打包好的项目只能放在指定的目录下才能运行,若是放在别处,路径仍然是错误的。

难道这种需要多处放的项目只能使用 hashHistory 吗?

关于教程中有一点没有说明清楚,当父Route下存在多个IndexRoute,只有最后的IndexRouter会生效

今天重新好好看了一遍,再做了一遍,感觉不错了终于

十二,路由的钩子例子中

/messages/:id的onLeave
/inbox的onLeave
/about的onEnter

第二个应该是 "/messages 的 onLeave"

随处可见阮老师的教程,详细而又简洁,受益匪浅。上次逛豆瓣的时候竟然也看到了阮老师的文章,我真的是吃了一鲸!现在是万分膜拜了!

const requireAuth = (nextState, replace) => {
if (!auth.isAdmin()) {
// Redirect to Home page if not an Admin
replace({ pathname: '/' })
}
}
export const AdminRoutes = () => {
return (

)
}


请问里面的replace是自定义函数?

hashHistory和browserHistory的区别还是不太明白,难道hashHistory的背后就不是调用浏览器的history api吗? browserHistory需要服务器配合,那是不是说browserHistory就不是spa了?

引用ManC的发言:

阮老师,请教下如何去除去是URL中的?_k参数?


如果只是想去掉 ?_k=adseis 这样的字符串的话,可以使用外部的 history 模块。

import { createHashHistory } from 'history';

const appHistory = useRouterHistory(createHashHistory)({ queryKey: false });

ReactDOM.render(
<Router history={appHistory}>
{routes}
</Router>,
document.getElementById('app')
);

我有一个疑问 官方的示例上第14个例子 为什么通过 http://localhost:8080/ 无法测试了
显示 Cannot GET /

引用lihuihero的发言:

我有一个疑问 官方的示例上第14个例子 为什么通过 http://localhost:8080/ 无法测试了
显示 Cannot GET /



在window环境下命令窗口里应该如下使用: 这个应该先执行 set node_env=production 然后在执行 npm start 而不是一整行一次执行。这样就起作用了,你可以试试
我照着这个试来一次 没问题了 能看了。 这14和13的例子 是交大家怎么配合 EXPRESS设置路由是吗?

我实在看不明白要这个router做什么用,我是asp.net mvc开发者,这无疑给页面又多了一个js文件,mvc的route已经很好了,要这个react router有嘛用?

如果用Route嵌套是不是太麻烦,还要弄一个中间件设置props.children,大家有没有更简便的方式呢?

path的/能加个随机数吗?加个随机数如何不影响页面?求解

引用Airma的发言:

刚入们小白学习react求解答:
router的嵌套使用没有效果啊,

<Route path="/" component={App}>
<Route path="/demo" component={demo}/>
</Route>

我定义了两个组件app和haha,让他们返回app和demo,
然后我输入了/demo这个url,却没有渲染demo,只有一个app

做了个实验,这种嵌套式一定要从主页点进去,单独/demo进入url会找不到路径。不知道是不是这个意思

引用奕佚的发言:

您好,我想请教您作为一个前端菜鸟,应该怎样去学习呢?我一直想学点东西,但是每次在学习的过程中遇到一些陌生的框架或者库什么的,就想着又去学那个,所以每次都是半途而废,好纠结啊

我个人觉得你这种做法也是对的,大致的了解下各个框架的入门,再选择一门自己喜欢和感兴趣的深入学习,作为一个同样是学习者的建议

不知道为啥很喜欢学react相关的技术,学了一坨。。。
但就是没开发个像样的项目。。。。

PATH 属性部分:不管路径是否匹配,总是会加载指定组件。 这句不是很理解,从例子里面看不出来是解释这句话

引用Ricky的发言:

大家使用 import {Router,Route,Link} from 'react-router';这种写法,在浏览器中打开难道没遇到 require not defined的报错消息吗?

ES6

有一块组件按需加载好像没讲到。

引用Airma的发言:

刚入们小白学习react求解答:
router的嵌套使用没有效果啊,

<Route path="/" component={App}>
<Route path="/demo" component={demo}/>
</Route>

我定义了两个组件app和haha,让他们返回app和demo,
然后我输入了/demo这个url,却没有渲染demo,只有一个app

component={demo}返回的组件大写试试?如:Demo
如果没记错的话react组件首字母需要大写

动态路由问题
export default (store) => ({
path: 'route/:id',
getComponent (nextState, cb) {
require.ensure([], (require) => {
const Route = require('./components/Route').default
cb(null, Route)
})
}
})

问:这种异步动态路由,是否比阮师 的写法更好一些呢?

谢谢阮老师 你的文章对我帮助很大

Link 使用要引入let Link = require('react-router').Link,没说明还不知道突然多一个Link是什么

引用您在路由嵌套上面的文字:‘上面代码中,用户访问/repos时,会先加载App组件,然后在它的内部再加载Repos组件。’但是经过多次测试,路由访问是不会调用app这个组件的,不知道哪里有误

还有一个问题: http://localhost:8080/#/ 这个样子初始化的时候调用app组件是调用一次,但是在实际的开发中,一般的url http://localhost:8080/是不带后面/#这样子的情况下刷新页面,是会调用两次app组件的

感谢,很受用,官方现在更新了4.0很多都不一样了。

您好,请问如果访问http://localhost:8080/时,默认显示的是/about路径下的内容,不是home下的内容,怎么实现

react-router 4.0版本已没有 hashHistory 这个方法,需要用react-router 2.0版本

browserHistory hashHistory 这些都不包含在router里面吧?

onEnter 那里,replace is not a function

建议老师在开头申明下react-router的版本,我用的时候已经v4了,有变化





我这边会报:Uncaught Error: A may have only one child element

引用Ziv的发言:
我这边会报:Uncaught Error: Amay have only one child element

引用Ziv的发言:
Router history={createBrowserHistory()} Route path="/" component={Index} Route path="/test2" component={Test2} Router (为了方便显示简写的) 我这边会报:Uncaught Error: Amay have only one child element

已经学习三周了,回头过来,老师的这句话感触最深。“你会发现,它不是一个库,也不是一个框架,而是一个庞大的体系。想要发挥它的威力,整个技术栈都要配合它改造。你要学习一整套解决方案,从后端到前端,都是全新的做法”

4.0.0是这样写的吗?我这样写为啥是错的?

请问部署的时候,不能用 webpack-dev-server 了,通过 Nginx 作为 HTTP 服务器。这种情况,怎么才能“针对服务器改造”,让它支持 ‘createMemoryHistory’?

改变url,难道不能直接 location.href = 或者 location.hash = 吗!!!!!!

你这个是不是已经过期了,现在有一个react-router-dom

你好,阮老师,第五模块:IndexRoute 组件,您讲的“上面代码中,访问根路径/,不会加载任何子组件。也就是说,App组件的this.props.children,这时是undefined”,为什么我能顺利的加载出来?我也没发现那段代码有什么特殊之处,除了子路由前面没有斜杠。

请教,react里面跳转外部链接的问题,如果想在APP里面点一个按钮跳转到一个外部页面,比如www.baidu.com,这个路由应该怎么写?我直接写的 window.location.href = url; 但是地址栏 变成这样了http://localhost:8989/#/www.baidu.com

引用webkws的发言:

ES6

用的是es6,语法,报错了,是不应该用es6的语法吗?

阮老师,我们这个因为各种原因,需要react嵌入在jsp中,那redux框架还能用吗

@li:

可以用。Redux 与后台语言无关。

@Airma:

你看下App组件里面有没有加入{this.props.children}

阮老师 react动态路由 各模块css重复问题怎么解决啊?

browserHistory 服务器配置 链接失效了。

引用tianna的发言:

请教,react里面跳转外部链接的问题,如果想在APP里面点一个按钮跳转到一个外部页面,比如www.baidu.com,这个路由应该怎么写?我直接写的 window.location.href = url; 但是地址栏 变成这样了http://localhost:8989/#/www.baidu.com


这个问题你解决了吗?

软老师,我在官网下载的react路由例子,我这边运行会报错,你那边能发我一个一例子,我研究了好久,但是在路由哪里报错

想请教一下,在使用了routes参数传递给一个Router组件批量生成路由规则情况下,如何在路由匹配的组件中获取到react-router自带的match参数,试了好久我都没有成功

引用Airma的发言:

刚入们小白学习react求解答:
router的嵌套使用没有效果啊,

<Route path="/" component={App}>
<Route path="/demo" component={demo}/>
</Route>

我定义了两个组件app和haha,让他们返回app和demo,
然后我输入了/demo这个url,却没有渲染demo,只有一个app

确认react-router-dom的版本是不是4.x以上了,4.x以上的版本嵌套的方式不能这样写.

引用唐的发言:

4.0.0是这样写的吗?我这样写为啥是错的?


4.0版本已经改了,上面的是react-router2.0版本的
4.0版本参考这个或上GitHub看
http://www.jianshu.com/p/27ee7df4ccc1

谢过阮一峰老师,一直看阮老师的开源内容,很好。

阮老师,我不想打击您专研前端的积极性!但是我想说,React这一切的一切,缘起不都是因为html5规范考虑的不周全吗?我认为react领域里面有一些是http协议该考虑的问题,有一些是浏览器该考虑的问题!

http和html标准协议的制定和更新,需要您这样深耕的大牛去影响!而不是倒逼前端去营造N多小技巧!莫等到革新性的浏览器开发推广出来,这一切的一切纷纷扰扰,统统变为0。这样的努力是不是有点浪费?

“十、histroy 属性”的单词有拼写的小错误

服务器改造的链接无法打开?

react-router V4 不支持onEnter和onLeave钩子函数了吧。例子要更新了。。。

老师,我想请问一下,官方推荐bowserHistory,开发环境中用hashHistory会不会有什么问题?我们这儿项目马上开始了,我还在为选用路由而发愁。。。。。。。

请问老师,我在使用路由的时候,有一个组件我不需要重新渲染该怎么办?
举个例子:
(router用的是3.0.2版本)
render() {
return (








)
}

map对应的Route不想刷新怎么实现呢

这个已经是老教程了,不适应现在的 4.x 新版本了,很多api被废弃了,看了半天 一脸懵,没用。建议直接看官方文档。

@ReactLW:


你是想 避免刷新带来的性能问题吧,这个简单,你去看react的生命周期,有个方法 就是为这个问题而生的 。 建议 你把基础打好, 这都是 react 的 最基本的了。

照着官方demo做到Lesson 11,遇到了报错,发现bundle.js 内容居然和index.html相同!本地代码完全照教程写的,不知道有没有人遇到相同的问题,想请问如何解决?(上一条留言由于一个标签,没显示全,我重写了一次)

引用cheer的发言:

这个问题你解决了吗?


大神可以讲解一下4.x的路由吗?对于新手来说,跟4.0以前的版本差距有点大,有点无从下手~

阮老师您好,我想将提示用户"确认离开吗"案部分代码放到全局该怎么用?

React-router页面刷新的时候,不是停留在当前页面,而是被跳回了首页这个需要怎么处理?

@zergskj:

都8102年了,是不是有的项目还得去兼容IE?
你这是多虑了。。。

没VUE表示给一个大大的差评!!!!!

router4 希望改变还是蛮大,
不过还是挪到了4

引用迷梦情空的发言:

大神可以讲解一下4.x的路由吗?对于新手来说,跟4.0以前的版本差距有点大,有点无从下手~

(/:id)这个路由无法匹配

阮老师,to={{pathname: '/new', query: {p: 3}}}这样跳转页面,地址栏URL里没有query的参数,但new页面里能获取到location.query.a;

表单处理的跳转没有一个能用的。

现在来看,react 已经火爆全球了?

也可以用react-router-pro啊,感觉更简单

不知道该怎么深入学react。。。好纠结

毁灭吧,我累了,事实上我跟着官方示例走了一遍,我也不知道我干了什么。前面几个小项目还好,后面的跟着做也不能理解为什么这样?很多传值的地方不能够理解。在此之前我也学习了 react 的基础知识。我该怎么办?

@大亨:

replace是onEnter方法的参数,是Route设计好的

@Jayleonc:

别着急,慢慢学,只要在学,就有所得

引用weny的发言:

在window环境下命令窗口里应该如下使用:
这个应该先执行 set node_env=production
然后在执行 npm start
而不是一整行一次执行。这样就起作用了,你可以试试

set NODE_ENVE=XXX && npm XXX

非常赞,组织清晰,重点突出。 之前用的是Vue全家桶,近期学习下React全家桶。 先看的《React Router 中文文档》,组织很混乱,重点不突出,看的很累。 还是大佬的博客清晰。

最新v6版本 本文已经过时

非常感谢,搜索了那么多资料就在这里找到想要的

我要发表看法

«-必填

«-必填,不公开

«-我信任你,不会填写广告链接