react路由-学习

React Router 中的组件主要分为三类:

  • 路由器,例如 BrowserRouter 和 HashRouter
  • 路由匹配器,例如 Route 和 Switch
  • 导航,例如 Link,NavLink 和 Redirect

在 Web 应用程序中使用的所有组件建议都从 react-router-dom 导入

1、安装路由包

npm i react-router-dom --save

2、路由组件

路由组件分为两种:BrowserRouter(history 模式) 和 HashRouter(hash 模式),用法一样,但是 url 展示不一样,其中 hash 模式带有 # 号符,如下所示:

  • history 模式:http://localhost:3000/page2
  • hash 模式:http://localhost:3000/#/page2

2.1、BrowserRouter

class App extends React.Component {
  render () {
    return (
      <BrowserRouter>
        <Route path="/page1" exact component={Page1}></Route>
        <Route path="/page2" exact component={Page2}></Route>
        <Route path="/page3/:id" exact component={Page3}></Route>
      </BrowserRouter>
    );
  }
}

2.2、HashRouter

class App extends React.Component {
  render () {
    return (
      <HashRouter>
        <Route path="/page1" exact component={Page1}></Route>
        <Route path="/page2" exact component={Page2}></Route>
        <Route path="/page3/:id" exact component={Page3}></Route>
      </HashRouter>
    );
  }
}

3、Route 参数

3.1、path

string 类型,用来指定路由跳转路径,如下所示,根据 path 和 url 匹配到对应的页面

// 路由配置
<Route path="/page1" exact component={Page1}></Route>

// 页面访问
http://localhost:3000/page1

3.2、exact

boolean 类型,用来精确匹配路由,如果为 true 则精确匹配,否则为正常匹配;如下所示

// exact = true 时
// 路由配置
<Route path="/page1" exact component={Page1}></Route>
// 浏览器通过以下 url 访问不到 page1 页面
http://localhost:3000/page1/one


// exact = fasle 时
// 路由配置
<Route path="/page1" exact={false} component={Page1}></Route>
// 浏览器通过以下 url 可以访问到 page1 页面
http://localhost:3000/page1/one

3.3、sensitive

boolean 类型,用来设置是否区分路由大小写,如果为 true 则区分大小写,否则不区分;如下所示

// sensitive = true 时
// 路由配置
<Route path="/page1" sensitive component={Page1}></Route>
// 浏览器通过以下 url 访问不到 page1 页面
http://localhost:3000/PAGE1


// sensitive = fasle 时
// 路由配置
<Route path="/page1" sensitive={false} component={Page1}></Route>
// 浏览器通过以下 url 可以访问到 page1 页面
http://localhost:3000/PAGE1

3.4、strict

boolean 类型,对路径末尾斜杠的匹配。如果为 true,path 为 ‘/page1/’ 将不能匹配 ‘/page1’ 但可以匹配 ‘/page1/one’。;如下所示

// 路由配置
// strict = true 时
<Route path="/page1/" strict component={Page1}></Route>
// 浏览器通过以下 url 访问不到 page1 页面
http://localhost:3000/page1
// 浏览器通过以下 url 可以访问到 page1 页面
http://localhost:3000/page1/one


// strict = fasle 时
// 路由配置
<Route path="/page1/" strict={false} component={Page1}></Route>
// 浏览器通过以下 url 可以访问到 page1 页面
http://localhost:3000/page1
http://localhost:3000/page1/one

3.5、component

设置路由对应渲染的组件,如下所示

   <Route path="/page1/" exact component={Page1}></Route>
3.6、render

(1)通过写 render 函数返回具体的 dom,如下所示

<Route path="/page1/" exact render={() => (<div>this is page</div>)}></Route>

(2) 也可以通过写 render 函数返回组件,如下所示

<Route path="/page1/" exact render={() => (<Page1/>)}></Route>

这样写的好处是,不仅可以通过 render 方法传递 props 属性,并且可以传递自定义属性:

<Route path='/about' exact render={(props) => {
    return <Page1 {...props} name={'name1'} />
}}></Route>

然后,就可在 Page1 组件中获取 props 和 name 属性:

componentDidMount() {
    console.log(this.props) 
}


// this.props:
// history: {length: 9, action: "POP", location: {…}, createHref: ƒ, push: ƒ, …}
// location: {pathname: "/home", search: "", hash: "", state: undefined, key: "ad7bco"}
// match: {path: "/home", url: "/home", isExact: true, params: {…}}
// name: "name1"

4、Switch

如果路由 Route 外部包裹 Switch 时,路由匹配到对应的组件后,就不会继续渲染其他组件了。但是如果外部不包裹 Switch 时,所有路由组件会先渲染一遍,然后选择所有匹配的路由进行显示。
(1)当没有使用 Switch 时,如下所示

// 路由配置
<BrowserRouter>
 <Route path="/page1" component={Page1}></Route>
 <Route path="/" component={Page2}></Route>
 <Route path="/page3/:id" exact component={Page3}></Route>
</BrowserRouter>

// 当面访问以下 url 时,浏览器会同时显示 page1 和 page2 页面的内容 
http://localhost:3000/page1

(2)当使用 Switch 时,如下所示

// 路由配置
<BrowserRouter>
 <Switch>
   <Route path="/page1" component={Page1}></Route>
   <Route path="/" component={Page2}></Route>
   <Route path="/page3/:id" exact component={Page3}></Route>
 </Switch>
</BrowserRouter>

// 当面访问以下 url 时,浏览器只会显示 page1 页面的内容 
http://localhost:3000/page1

5、Link 和 NavLink

Link 和 NavLink 都可以用来指定路由跳转,NavLink 的可选参数更多。

5.1、Link

**(1)通过字符串执行路由跳转**
<Link to='/page2'>
  <span>跳转到 page2</span>
</Link>  

(2)通过对象指定路由跳转

  • pathname: 表示跳转的页面路由 path
  • search: 表示查询参数的字符串形式,即等同于 location 中的 search
  • hash: 放入网址的 hash,即等同于 location 中的 hash
  • state: 可以通过这个属性,向新的页面隐式传参,如下所示,page2 中可以通过 this.props.location.state 可以拿到 age: 11;
  <Link to={{
    pathname: '/page2',
    search: '?name=name1',
    hash: '#someHash',
    state: { age: 11 }
  }}>
  <span>跳转到 page2</span>
</Link>

(3) replace

如果设置 replace 为 true 时,表示路由重定向,即新地址替换掉上一次访问的地址;

5.2、NavLink

这是 的特殊版,顾名思义这就是为页面导航准备的。因为导航需要有 “激活状态”。

(1)activeClassName: string

导航选中激活时候应用的样式名,默认样式名为 active

<NavLink
 to="/page2"
 activeClassName="selected"
>跳转到 page2</NavLink>

(2)activeStyle: object

如果不想使用样式名就直接写 style,如下所示

<NavLink
  to="/page2"
  activeStyle={{ color: 'green', fontWeight: 'bold' }}
>跳转到 page2</NavLink>

(3)exact: bool

若为 true,只有当访问地址严格匹配时激活样式才会应用,跟 3.2 的 exact 一个道理;

(4)strict: bool

若为 true,只有当访问地址后缀斜杠严格匹配(有或无)时激活样式才会应用,跟 3.4 的 exact 一个道理;

(5)isActive: func

决定导航是否激活,或者在导航激活时候做点别的事情。不管怎样,它不能决定对应页面是否可以渲染。

6、Redirect

将导航到一个新的地址,即重定向;如下所示,当页面访问到 /page3 时,页面会直接重定向到 page3.

<BrowserRouter>
  <Switch>
    <Route path="/page1" exact component={Page1}></Route>
    <Route path="/page2" exact component={Page2}></Route>
    <Route path="/page3" exact component={Page3}></Route>
  </Switch>
</BrowserRouter>

当然,也可以使用对象的形式,如下所示

<Redirect
 to={{
   pathname: "/page3",
   search: "?name=tom",
   state: { age: 11 }
 }}
/>

7、History 对象 - 编程式导航

支持字符串作为参数跳转,如下所示

   this.props.history.push('/page2');

同样支持对象作为参数进行路由跳转,如下所示

this.props.history.push({
  pathname: '/page2',
  state: {
    name:'tom'
  }
});

跳转到对应的页面,我们打印出对应 history 对象,可以看到有以下属性

在这里插入图片描述

以上 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 类型) 阻止跳转

    8、withRouter

    withRouter 可以将一个非路由组件包裹为路由组件,使这个非路由组件也能访问到当前路由的 match, location, history对象。使用场景:即如果想在路由页面的子组件中,进行路由的跳转,需要使用 withRouter 进行包裹,否则子组件是访问不到路由对象的。

    (1)没有使用 withRouter 的场景

    如下代码所示,我们没有使用 withRouter 对 Component1 组件进行包裹,当我们在 Component1 中调用 history 时会报错 TypeError: Cannot read property ‘push’ of undefined

class Component1 extends React.Component<any> {
  handleClick () {
    this.props.history.push('/page2');
  }
  render () {
    return <div onClick={() => this.handleClick()}>this is component1</div>;
  }
}

export default Component1;

(2)使用 withRouter 的场景

如下代码所示,我们使用 withRouter 对 Component1 组件进行包裹,当我们在 Component1 中调用 history 时能正常进行路由页面跳转

class Component1 extends React.Component<any> {
  handleClick () {
    this.props.history.push('/page2');
  }
  render () {
    return <div onClick={() => this.handleClick()}>this is component1</div>;
  }
}

export default withRouter(Component1);

9、参数传递

9.1、params 传参

路由配置如下

<Route path="/page2/:id" exact component={Page2}></Route>

路由跳转代码如下

this.props.history.push('/page2/1000');

参数获取代码如下

this.props.match.params;  // {id: "1000"}

9.2、query 传参

query 方式可以传递任意类型的值,但是页面的 url 也是由 query 的值拼接的,url 很长且是明文传输。
路由传参如下

//数据定义
const data = {id:3,name:sam,age:36};
const path = {
    pathname: '/user',
    query: data,
}
this.props.history.push(path);

页面获取路由传过来的参数如下

//页面取值
const data = this.props.location.query;

9.3、隐式传参

路由跳转传参如下

this.props.history.push({
  pathname: '/page2',
  state: {
    name:'tom'
  }
});

参数获取代码如下

this.props.history.location.state  // name: tom

通过以上配置后,我们就完成整个 react 项目的路由配置,后续我们在功能需求迭代中,只需要尽情地编写业务代码以及使用 Link/NavLink 或者 this.props.history 进行路由的跳转即可。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值