React Router--React Router4
2017-09-09 17:39
183 查看
React的路由其实就是一个React组件,路由要通过Route组件定义。例子:
上面代码中,用户访问根路由/home时,组件会先加载App组件,然后在加载Home组件。而App组件要写成以下:
上面代码中,App组件的this.props.children属性就是子组件。
这样看react的路由就是一个组件,最外层的route对应的是组建App,当访问/时,加载App组件,而加载里面的嵌套的路由时,会在App内部的this.props.children加载相应的组件。
IndexRoute
IndexRoute是指定当访问跟路由的时候this.props.children默认加载的组件。
IndexRedirect
IndexRedirect组件用于访问根路由的时候,将用户重定向到某个子组件。
histroy 属性
Router组件的history属性,用来监听浏览器地址栏的变化,并将URL解析成一个地址对象,供 React Router 匹配。
history属性,一共可以设置三种值
1.hashHistory:路由将通过URL的hash部分(#)切换。
2.browserHistory:浏览器的路由就不再通过Hash完成了,而显示正常的路径。
3.createMemoryHistory:主要用于服务器渲染。
路由的钩子
每个路由都有Enter和Leave钩子,用户进入或离开该路由时触发
例如
React Router4
以上我们讲解了Router4以前的版本,在v3中的一些思想到了v4,已经不正确了,
1.所有的路由全部订应在一起。
2.布局是通过<Route>组件的嵌套而来的。
3.布局和页面组件是完全纯粹的,它们是路由的一部分。
如果以上代码用v4实现:
路由直接被定义到App组建里,即之前的this.props.children
产生了新的api:
BrowserRouter:代表浏览器router,而且我们现在从 react-router-dom 中导入它。
HashRouter:路由将通过URL的hash部分(#)切换。
MemoryRouter: 主要用于服务器渲染。
包容性路由
V3 的路由规则是“排他性”的,这意味着只有一条路由将获胜,在this.props.children里面最终只加载一个组件。
但是,V4的路由规则是包容的,假如没有exact ,那么则会加载所有组件。例如上例中,当访问 / 时,默认加载App组件,但是App组件下还有Home、Login、ImgUpload,这些将都被渲染。
Paste_Image.png
排他性路由
如果你只需要在路由列表里匹配一个路由,则使用 <Switch> 来启用排他路由:
在此处,我们依然需要加上exact,因为无论你访问 /ImgUpload
/login 主页的路径也将被匹配,所以会先显示 Home,但是Switch只允许一条路由生效,所以无论你点login、还是ImgUpload,它永远显示的事Home。所以在配置顺序上要做一些调整,例如将 / 放到最后。
如果要是,加上 exact 则不需要考虑顺序问题了。
“默认路由”和“未找到”
V4中代替IndexRoute的 是<Route exact>;
如果没有路由解析,则可以使用 <Switch> 与 <Redirect>重定向到具有有效路径的默认页面。
嵌套布局
在V3使用嵌套布局:
app.js
person.js
如果使用V4,我们只需要在嵌套的组件里面设计:
App.js
person.tsx
main.tsx
在组建的props中,存在一个match对象,我们打印一下:
Paste_Image.png
我们可以拿到 当前组建的路由,因此在person.js可以这样
match 对象给我们提供了几个属性,包括 match.params、match.path、match.url
match.path vs match.url
在上述代码中,我们打印一下User里面的match可以发现
match.path:
match.path
match.url:
Paste_Image.png
一个是我们设计的路由,一个是当前访问的裸游;
match.path常用来构建新的路由。
match.url常用来构建嵌套的link
渲染出来:
http://localhost:3000/person/12/add
授权路由
在应用程序中,通常会根据用户的登录状态来限制用户访问某些路由。对于未经授权的页面(如“登录”和“忘记密码”)与已授权的页面(应用程序的主要部分)看起来不一样也是常见的。为了解决这些需求,需要考虑一个应用程序的主要入口点:
使用
react-redux 与 React Router v4 非常类似,就像之前一样,只需将 BrowserRouter
包在 <Provider>
中即可。
通过这种方法可以得到一些启发。第一个是根据我们所在的应用程序的哪个部分,在两个顶层布局之间进行选择。像访问 /auth/login 或 /auth/forgot-password 这样的路径会使用 UnauthorizedLayout —— 一个看起来适于这种情况的布局。当用户登录时,我们将确保所有路径都有一个 /app 前缀,它使用 AuthorizedRoute 来确定用户是否登录。如果用户在没有登录的情况下,尝试访问以 /app 开头的页面,那么将被重定向到登录页面。
v4 中一个惊人的新功能是能够为特定的目的创建你自己的路由。它不是将 component 的属性传递给 <Route>,而是传递一个 render 回调函数:
<Link> vs <NavLink>
<NavLink>与 <Link>一样,但如果 <NavLink>匹配浏览器的 URL,那么它可以提供一些额外的样式能力。例如,在示例应用程序中,有一个<PrimaryHeader>
组件看起来像这样:
使用 <NavLink> 可以让我给任何一个激活的链接设置一个 active 样式。而且,需要注意的是,我也可以给它们添加 exact 属性。如果没有 exact,由于 v4 的包容性匹配策略,那么在访问 /app/users 时,主页的链接将处于激活中。
NavLink 带 exact 属性等价于 v3 的 <link>,而且更稳定。
参考文章:
[译] 关于 React Router 4 的一切
All About React Router 4
作者:Dabao123
链接:http://www.jianshu.com/p/9ffeb2ee4f38
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
import * as React from "react"; import {IndexRedirect ,Route} from 'react-router'; import Home from '../components/home'; import ImgUpload from '../components/uploadImg'; import Login from '../components/Login'; import App from '../contains/App'; export default ( <Route path="/" component={App}> <IndexRedirect to='home' /> <Route path="home" component={Home} /> <Route path="login" component={Login} /> <Route path="imgLoad" component={ImgUpload} /> </Route> )
import * as React from 'react'; import * as ReactDom from 'react-dom'; import { Router ,browserHistory} from 'react-router'; import routes from '../router'; ReactDom.render( <Router history={browserHistory} routes={routes} />, document.getElementById('app') )
上面代码中,用户访问根路由/home时,组件会先加载App组件,然后在加载Home组件。而App组件要写成以下:
import * as React from 'react' import * as ReactDom from 'react-dom' interface IAppProps {} interface IAppState {} export default class App extends React.Component<IAppProps,IAppState> { constructor(props) { super(props) } render() { return ( <div> {this.props.children} </div> ) } }
上面代码中,App组件的this.props.children属性就是子组件。
这样看react的路由就是一个组件,最外层的route对应的是组建App,当访问/时,加载App组件,而加载里面的嵌套的路由时,会在App内部的this.props.children加载相应的组件。
IndexRoute
IndexRoute是指定当访问跟路由的时候this.props.children默认加载的组件。
IndexRedirect
IndexRedirect组件用于访问根路由的时候,将用户重定向到某个子组件。
histroy 属性
Router组件的history属性,用来监听浏览器地址栏的变化,并将URL解析成一个地址对象,供 React Router 匹配。
history属性,一共可以设置三种值
1.hashHistory:路由将通过URL的hash部分(#)切换。
2.browserHistory:浏览器的路由就不再通过Hash完成了,而显示正常的路径。
3.createMemoryHistory:主要用于服务器渲染。
路由的钩子
每个路由都有Enter和Leave钩子,用户进入或离开该路由时触发
例如
<Route path="messages/:id" onEnter={ ({params}, replace) => replace(`/messages/${params.id}`) } />
React Router4
以上我们讲解了Router4以前的版本,在v3中的一些思想到了v4,已经不正确了,
1.所有的路由全部订应在一起。
2.布局是通过<Route>组件的嵌套而来的。
3.布局和页面组件是完全纯粹的,它们是路由的一部分。
如果以上代码用v4实现:
import * as React from 'react' import { BrowserRouter, Route, Link} from 'react-router-dom' import Home from '../components/home'; import ImgUpload from '../components/uploadImg'; import Login from '../components/Login'; export const App = () => ( <BrowserRouter> <div> <Route path="/" exact component={Home} /> <Route path="home" component={Home} /> <Route path="login" component={Login} /> <Route path="imgLoad" component={ImgUpload} /> </div> </BrowserRouter> )
import * as React from 'react'; import * as ReactDom from 'react-dom'; import {App} from '../contains/App'; ReactDom.render( <App />, document.getElementById('app') )
路由直接被定义到App组建里,即之前的this.props.children
产生了新的api:
BrowserRouter:代表浏览器router,而且我们现在从 react-router-dom 中导入它。
HashRouter:路由将通过URL的hash部分(#)切换。
MemoryRouter: 主要用于服务器渲染。
包容性路由
V3 的路由规则是“排他性”的,这意味着只有一条路由将获胜,在this.props.children里面最终只加载一个组件。
但是,V4的路由规则是包容的,假如没有exact ,那么则会加载所有组件。例如上例中,当访问 / 时,默认加载App组件,但是App组件下还有Home、Login、ImgUpload,这些将都被渲染。
Paste_Image.png
排他性路由
如果你只需要在路由列表里匹配一个路由,则使用 <Switch> 来启用排他路由:
export const App = () => ( <BrowserRouter> <div> <Switch> <Route path="/" exact component={Home} /> <Route path="home" component={Home} /> <Route path="login" component={Login} /> <Route path="imgLoad" component={ImgUpload} /> </Switch> </div> </BrowserRouter> )
在此处,我们依然需要加上exact,因为无论你访问 /ImgUpload
/login 主页的路径也将被匹配,所以会先显示 Home,但是Switch只允许一条路由生效,所以无论你点login、还是ImgUpload,它永远显示的事Home。所以在配置顺序上要做一些调整,例如将 / 放到最后。
如果要是,加上 exact 则不需要考虑顺序问题了。
“默认路由”和“未找到”
V4中代替IndexRoute的 是<Route exact>;
如果没有路由解析,则可以使用 <Switch> 与 <Redirect>重定向到具有有效路径的默认页面。
嵌套布局
在V3使用嵌套布局:
export default ( <Route path="/" component={App}> <IndexRedirect to='home' component={Home}/> <Route path="home" component={Home} /> <Route path="login" component={Login} /> <Route path="imgLoad" component={ImgUpload} /> <Route path="Person" component={Person} > <IndexRedirect to='center'/> <Route path="center" component={Center} /> <Route path="like" component={Like} /> </Route> </Route> )
app.js
export default class App extends React.Component<IAppProps,IAppState> { constructor(props) { super(props) } render() { return ( <div> {this.props.children} </div> ) } }
person.js
export default class Person extends React.Component<any,any>{ constructor(props){ super(props) } render(){ return ( <div> <div className="nav-wrap"> <ul className="nav"> <li><Link to="/home">首页</Link></li> <li><Link to="/imgLoad">上传</Link></li> <li><Link to="/login">登陆</Link></li> <li><Link to="/Person">个人</Link></li> </ul> </div> <div> <ul className="nav"> <li><Link to="/Person/center">center</Link></li> <li><Link to="/Person/like">like</Link></li> </ul> {this.props.children} </div> </div> ) } }
如果使用V4,我们只需要在嵌套的组件里面设计:
App.js
export const App = () => ( <BrowserRouter> <div> <Switch> <Route path="/" exact component={Home} /> <Route path="/login" component={Login} /> <Route path="/imgLoad" component={ImgUpload} /> <Route path="/imgLoad" component={ImgUpload} /> <Route path="/person" component={Person} /> </Switch> </div> </BrowserRouter> )
person.tsx
interface states { id : Number, [propName:string] : any } export default class Person extends React.Component<any,states>{ constructor(props){ super(props) this.state = { id : 12 } } render(){ return ( <div> <div className="nav-wrap"> <ul className="nav"> <li><Link to="/">首页</Link></li> <li><Link to="/imgLoad">上传</Link></li> <li><Link to="/login">登陆</Link></li> <li><Link to="/person">person</Link></li> </ul> </div> <div> <ul className="nav"> <li><Link to="/person">center</Link></li> <li><Link to="/person/like">like</Link></li> <li><Link to={`/person/${this.state.id}`}>user</Link></li> </ul> <div> this is person </div> <div> <Switch> <Route path={this.props.match.path} exact component={Center} /> <Route path={`${this.props.match.path}/like`} component={Like} /> <Route path={`${this.props.match.path}/:userId`} component={User} /> </Switch> </div> </div> </div> ) } }
main.tsx
ReactDom.render( <App />, document.getElementById('app') )
在组建的props中,存在一个match对象,我们打印一下:
Paste_Image.png
我们可以拿到 当前组建的路由,因此在person.js可以这样
<Switch> <Route path={this.props.match.path} exact component={Center} /> <Route path={`${this.props.match.path}/like`} component={Like} /> <Route path={`${this.props.match.path}/:userId`} component={User} /> </Switch>
match 对象给我们提供了几个属性,包括 match.params、match.path、match.url
match.path vs match.url
在上述代码中,我们打印一下User里面的match可以发现
match.path:
match.path
match.url:
Paste_Image.png
一个是我们设计的路由,一个是当前访问的裸游;
match.path常用来构建新的路由。
match.url常用来构建嵌套的link
<li><Link to={`${this.props.match.url}/add`}>add</Link></li>
渲染出来:
http://localhost:3000/person/12/add
授权路由
在应用程序中,通常会根据用户的登录状态来限制用户访问某些路由。对于未经授权的页面(如“登录”和“忘记密码”)与已授权的页面(应用程序的主要部分)看起来不一样也是常见的。为了解决这些需求,需要考虑一个应用程序的主要入口点:
class App extends React.Component { render() { return ( <Provider store={store}> <BrowserRouter> <Switch> <Route path="/auth" component={UnauthorizedLayout} /> <AuthorizedRoute path="/app" component={PrimaryLayout} /> </Switch> </BrowserRouter> </Provider> ) } }
使用
react-redux 与 React Router v4 非常类似,就像之前一样,只需将 BrowserRouter
包在 <Provider>
中即可。
通过这种方法可以得到一些启发。第一个是根据我们所在的应用程序的哪个部分,在两个顶层布局之间进行选择。像访问 /auth/login 或 /auth/forgot-password 这样的路径会使用 UnauthorizedLayout —— 一个看起来适于这种情况的布局。当用户登录时,我们将确保所有路径都有一个 /app 前缀,它使用 AuthorizedRoute 来确定用户是否登录。如果用户在没有登录的情况下,尝试访问以 /app 开头的页面,那么将被重定向到登录页面。
v4 中一个惊人的新功能是能够为特定的目的创建你自己的路由。它不是将 component 的属性传递给 <Route>,而是传递一个 render 回调函数:
class AuthorizedRoute extends React.Component { componentWillMount() { getLoggedUser() } render() { const { component: Component, pending, logged, ...rest } = this.props return ( <Route {...rest} render={props => { if (pending) return <div>Loading...</div> return logged ? <Component {...this.props} /> : <Redirect to="/auth/login" /> }} /> ) } }
<Link> vs <NavLink>
<NavLink>与 <Link>一样,但如果 <NavLink>匹配浏览器的 URL,那么它可以提供一些额外的样式能力。例如,在示例应用程序中,有一个<PrimaryHeader>
组件看起来像这样:
const PrimaryHeader = () => ( <header className="primary-header"> <h1>Welcome to our app!</h1> <nav> <NavLink to="/app" exact activeClassName="active">Home</NavLink> <NavLink to="/app/users" activeClassName="active">Users</NavLink> <NavLink to="/app/products" activeClassName="active">Products</NavLink> </nav> </header> )
使用 <NavLink> 可以让我给任何一个激活的链接设置一个 active 样式。而且,需要注意的是,我也可以给它们添加 exact 属性。如果没有 exact,由于 v4 的包容性匹配策略,那么在访问 /app/users 时,主页的链接将处于激活中。
NavLink 带 exact 属性等价于 v3 的 <link>,而且更稳定。
参考文章:
[译] 关于 React Router 4 的一切
All About React Router 4
作者:Dabao123
链接:http://www.jianshu.com/p/9ffeb2ee4f38
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
相关文章推荐
- Webpack懒加载React Router的页面组件
- React-Router 4 的新玩意儿
- react-router 4.0 格式化文档
- react路由基础(Router、Link和Route)
- react-router 4.2版本的升级
- react-router JS 控制路由跳转实例
- React-Router 中文简明教程(上)
- 试着用React写项目-利用react-router解决跳转路由等问题(三)
- (二)创建react-router路由
- [Redux] Filtering Redux State with React Router Params
- Webpack + react-router 按需加载
- React And TypeScript(三:集成React-Router和React-Router-Redux)
- 前端路由实现与 react-router 源码分析 React
- React-router路由实践
- 基于react+react-router+redux+socket.io+koa开发一个聊天室
- React-Router (version 4)
- 17-7-26-react-router入门
- react-router HashRouter和BrowserRouter的使用
- react-router那些事儿
- nginx正确服务react-router应用