react路由的学习
2021/7/1 6:23:40
本文主要是介绍react路由的学习,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
react-router
单页面富应用(SPA):整个web应用实际上只有一个页面,当URL发生改变时,并不会从服务器去请求新的静态资源,而是通过js监听URL的改变,并且根据URL的 不同去渲染新的页面;而前端路由便维护着URL和具体页面组件的映射关系,最终我们在页面上看到的实际就是渲染的一个个组件页面。
前端路由原理:监听URL发生改变,同时不引起页面的刷新有两个方法:
(1)通过URL的hash改变URL。
(2)通过HTML5的history模式修改URL。
hash模式的原理
本质上是监听window的hashchange事件,然后根据具体的hash值来判断所要显示的内容;注意:hash模式的优势就是兼容性更好,在老版本的IE都可以运行。但是缺陷就是路径后有一个#,显得不像一个真实的路径。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=, initial-scale=1.0" /> <title>秃头的科比</title> </head> <body> <div> <a href="#/home">首页</a> <a href="#/about">关于</a> <div class="router-view"></div> </div> <script> var routerViewEl = document.getElementsByClassName("router-view")[0]; window.addEventListener("hashchange", function () { //根据具体的hash值来判断显示的内容 switch (location.hash) { case "#/home": routerViewEl.innerHTML = "首页"; break; case "#/about": routerViewEl.innerHTML = "关于"; break; default: routerViewEl.innerHTML = ""; } }); </script> </body> </html>
history模式
history模式是HTML5新增的,它有6种模式修改URL而不刷新页面:
(1)replaceState:替换原来的路径;
(2)pushState:使用新的路径;
(3)popState:路径的回退;
(4)go:向前或向后改变路径;
(5)back:向后改变路径;
(6)forward:向前改变路径。
history模式实现原理:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>history原理</title> </head> <body> <div id="app"> <a href="/home">首页</a> <a href="/about">关于</a> <div class="router-view"></div> </div> <script> // 1.获取router-view的DOM const routerViewEl = document.getElementsByClassName("router-view")[0]; // 获取所有的a元素, 自己来监听a元素的改变 const aEls = document.getElementsByTagName("a"); for (let el of aEls) { el.addEventListener("click", (e) => { e.preventDefault(); const href = el.getAttribute("href"); history.pushState({}, "", href); urlChange(); }); } // 执行回退操作时, 依然来到urlChange window.addEventListener("popstate", urlChange); // 监听URL的改变 function urlChange() { switch (location.pathname) { case "/home": routerViewEl.innerHTML = "首页"; break; case "/about": routerViewEl.innerHTML = "关于"; break; default: routerViewEl.innerHTML = ""; } } </script> </body> </html>
react-router从版本4开始,路由不再集中在一个包中进行管理了:
(1)react-router是router的核心部分代码;
(2)react-router-dom是用于浏览器的;
(3)react-router-native是用于原生应用的;
目前我们使用最新的react-router版本是5版本:实际上4和5版本的区别并不大。
react-router主要的一些API
(1)BrowserRouter和HashRouter:
BrowserRouter使用history模式。
HashRouter使用hash模式。
(2)Link和Navlink:
通常路径的跳转使用Link组件,其最终会被渲染成a元素。
NavLink是在Link的基础上可以添加一些样式属性。
to属性用于设置将要跳转到的路径。
(3)Route:用于路径的匹配;
path属性:用于设置匹配到的路径;
component属性:设置匹配到的页面组件;
exat:精准匹配,只要匹配到完全一致的路径,才会渲染对应的页面组件。
NavLink的使用
需求:路径选中时,对应的a元素变为红色。
这个时候,我们要使用NavLink组件来替代Link组件:
(1)activeStyle:活跃时匹配的样式;
<NavLink exact to="/" activeStyle={{color: "red", fontSize: "30px"}}>首页</NavLink> <NavLink to="/about" activeStyle={{color: "red", fontSize: "30px"}}>关于</NavLink> <NavLink to="/profile" activeStyle={{color: "red", fontSize: "30px"}}>我的</NavLink>
(2)activeClassName:活跃时添加的class,事实上在默认匹配成功时,NavLink就会自动给a标签添加上.active属性,但是为了避免样式重叠,推荐自定义class。
<NavLink exact to="/" activeClassName="link-active">首页</NavLink> <NavLink to="/about" activeClassName="link-active">关于</NavLink> <NavLink to="/profile" activeClassName="link-active">我的</NavLink> //样式 a.active, a.link-active { color: red; font-size: 30px; }
switch的作用
当我们匹配到某一个路径时,我们会发现有一些问题:
比如/about路径匹配到的同时,/:userid也被匹配到了,并且最后的一个NoMatch组件也总是被匹配到;
原因是什么呢?默认情况下,react-router中只要是路径被匹配到的Route对应的组件都会被渲染;
但是实际开发中,我们往往希望有一种排他的思想,只要匹配到了第一个,那么后面的就不应该继续匹配了,
这个时候我们可以使用Switch来将所有的Route进行包裹即可;
<Switch> <Route exact path="/" component={Home} /> <Route path="/about" component={About} /> <Route path="/profile" component={Profile} /> <Route path="/:id" component={User} /> <Route path="/user" component={User} /> <Route path="/login" component={Login} /> <Route path="/product" component={Product} /> <Route path="/detail/:id" component={Detail} /> <Route path="/detail2" component={Detail2} /> <Route path="/detail3" component={Detail3} /> <Route component={NoMatch} /> </Switch>
redirect的使用
Redirect用于路由的重定向,当这个组件出现时,就会执行跳转到对应的to路径中:
案例: 用户跳转到User界面;但是在User界面有一个isLogin用于记录用户是否登录:
true:那么显示用户的名称;
false:直接重定向到登录界面;
render() { return this.state.isLogin ? ( <div> <h2>User</h2> <h2>用户名: coderwhy</h2> </div> ): <Redirect to="/login"/> }
手动实现路由的跳转
目前我们实现的跳转主要是通过Link或者NavLink进行跳转的,实际上我们也可以通过JavaScript代码进行跳转。
但是通过JavaScript代码进行跳转有一个前提:必须获取到history对象。
如何可以获取到history的对象呢?
方式一:如果该组件是通过路由直接跳转过来的,那么可以直接获取history、location、match对象;
方式二:如果该组件是一个普通渲染的组件,那么不可以直接获取history、location、match对象;
那么如果普通的组件也希望获取对应的对象属性应该怎么做呢? 前面我们学习过高阶组件,可以在组件中添加想要的属性; react-router也是通过高阶组件为我们的组件添加相关的属性的;
如果我们希望在App组件中获取到history对象,必须满足一下两个条件:
(1)App组件必须包裹在Router组件之内;
(2)App组件使用withRouter高阶组件包裹;
import React, { PureComponent } from 'react'; import Product from './pages/product'; class App extends PureComponent { constructor(props) { super(props); } render() { return ( <div> <button onClick={e => this.jumpToProduct()}>商品</button> </div> ) } jumpToProduct() { this.props.history.push("/product"); } } export default withRouter(App);
路由的参数传递
传递参数有三种方式:
(1)动态路由的方式;
动态路由的概念指的是路由中的路径并不会固定:比如/detail的path对应一个组件Detail,而如果我们将path在Route匹配时写成/detail/:id,那么 /detail/abc、/detail/123都可以匹配到该Route,并且进行显示; 这个匹配规则,我们就称之为动态路由,通常情况下,我们使用动态路由传递一些简单的参数。
<NavLink to={`/detail/${id}`} activeClassName="link-active">详情</NavLink> <Switch> <Route path="/detail/:id" component={Detail} /> </Switch> //那么如何在组件中拿到这个id呢 render() { const match = this.props.match; console.log(match.params); return ( <div> <h2>Detail: {match.params.id}</h2> </div> ) }
(2)search传递参数;(这种方式不推荐使用)
<NavLink to={`/detail2?name=why&age=18`} activeClassName="link-active">详情2</NavLink> <Switch> <Route path="/detail2" component={Detail2} /> </Switch>
(3)Link中to传入对象;
<NavLink to={{ pathname: "/detail3", search: "name=abc", state: info }} activeClassName="link-active"> 详情</NavLink> <Switch> <Route path="/detail3" component={Detail3} /> </Switch>
react-router-config
目前我们所有的路由定义都是直接使用Route组件,并且添加属性来完成的。
但是这样的方式会让路由变得非常混乱,我们希望将所有的路由配置放到一个地方进行集中管理:这个时候可以使用react-router-config来完成; 安装react-router-config,配置路由映射的关系,使用renderRoutes函数完成配置。
{/* <Switch> <Route path="/detail3" component={Detail3} /> <Route component={NoMatch} /> </Switch> */} //一级路由 {renderRoutes(routes)} //子路由 {renderRoutes(this.props.route.routes)}
这篇关于react路由的学习的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-09-28基于Python+Vue开发的口腔牙科预约管理系统
- 2024-09-28基于Python+Vue开发的酒店客房预订管理系统
- 2024-09-27使用js将ETH账户的资产打散其他账户web3
- 2024-09-27我轻松地将我的 React.js 应用程序翻译成了多种语言。下面是我是如何做到的... ??
- 2024-09-27?? 使用 useMemo 和 useCallback 加速 React:告别缓慢的重新渲染!??
- 2024-09-27Vue CLI多环境配置教程:新手入门指南
- 2024-09-27Vue CLI多环境配置教程:快速入门指南
- 2024-09-27Vue CLI教程:新手入门指南
- 2024-09-27Vue CLI教程:初学者快速入门指南
- 2024-09-27Vue3公共组件教程:入门与实践