前言
React路由相关理解
📕 SPA的理解
- 单页WEB应用(single page web application , SPA)。
- 整个应用只有一个完整的页面。
- 点击页面的链接不会刷新页面,只会做页面的局部更新
- 数据都需要通过ajax请求获取,并在前端异步展现。
📗 路由的理解
1. 什么是路由?
2. 路由分类
📘 前端路由原理(重点)
前端路由依靠的是浏览器的BOM对象中的history,也就是浏览器的历史记录(history)。
但我们一般不直接操作BOM身上的history,而是借助history.js去操作BOM。
history模式的路由:
<script type="text/javascript" src="https://cdn.bootcss.com/history/4.7.2/history.js"></script>
<script type="text/javascript">
let history = History.createBrowserHistory() //方法一,直接使用H5推出的history身上的API
</script>
hash模式的路由:(地址栏中带有 # 号)
<script type="text/javascript" src="https://cdn.bootcss.com/history/4.7.2/history.js"></script>
<script type="text/javascript">
let history = History.createHashHistory() //方法二,hash值(锚点)
</script>
浏览器的历史记录(history)是一个栈的结构。
浏览器的历史记录(history)是一个栈的结构。
浏览器的历史记录(history)是一个栈的结构。
重要是事情说三遍。
每当执行push操作时,都是将path推入栈顶,浏览器也自动显示栈顶的内容。
function push(path) { // path:/test1
history.push(path)
return false
}
此时栈中有着至少两条数据,栈底是:localhost:5500,栈顶是刚刚push进来的 localhost:5500/test1
浏览器会显示栈顶路径对应的路由界面。
执行浏览器的回退操作其实就是将栈顶的 “/test1”出栈。
而执行replace操作时,是将目前栈顶的元素替换。
function replace(path) { // path: /test2
history.replace(path)
}
若原栈顶是 /test1,执行replace后则将栈顶的 /test1替换为 /test2,且显示的是 /test2 的路由界面。
监听路由发生变化
history.listen(location => {
console.log('请求路由路径变化了', location)
})
路由实现页面回退(将栈顶元素出栈)
history.goBack()
路由实现页面前进(将栈外元素推入栈顶)
history.goForward()
react-router-dom@5
- react的一个插件库
- 专门用来实现一个SPA应用
- 基于 React 的项目基本都会用到此库。
下载react-router-dom
npm install react-router-dom@5
yarn add react-router-dom@5
📙 基本路由使用
import React, { Component } from 'react'
import { NavLink, Route } from 'react-router-dom'
import Home from './pages/Home' // Home是路由组件
import About from './pages/About' // About是路由组件
import Header from './components/Header' // Header是一般组件
export default class App extends Component {
render() {
return (
<div>
<div className="row">
<div className="col-xs-offset-2 col-xs-8">
<Header />
</div>
</div>
<div className="row">
<div className="col-xs-2 col-xs-offset-2">
<div className="list-group">
{/* 原生html中靠<a>跳转不同的页面 */}
{/* <a href="./about.html" className="list-group-item">About</a>
<a href="./home.html" className="list-group-item">Home</a> */}
{/* 在React中靠路由链接实现切换组件—-编写路由链接 */}
<NavLink className="list-group-item" to="/about">About</NavLink>
<NavLink className="list-group-item" to="/home">Home</NavLink>
</div>
</div>
<div className="col-xs-6">
<div className="panel">
<div className="panel-body">
{/* 注册路由 */}
<Route path="/about" component={About} />
<Route path="/home" component={Home} />
</div>
</div>
</div>
</div>
</div>
)
}
}
这么写的话脚手架会报一个错误:
原因是,要在<NavLink>
标签以及<Route>
标签外面用<Router>
标签包裹起来。
我们可以在index.js中完成这个需求:
// index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import { BrowserRouter as Router } from 'react-router-dom'
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<Router>
<App />
</Router>
</React.StrictMode>
);
将整个App组件用Router标签包裹起来,这样就不会有报错啦。
📓 一般组件与路由组件
📓 路由API:Switch提高路由匹配效率(单一匹配)
不加switch:
<div className="panel-body">
{/* 注册路由 */}
<Route path="/about" component={About} />
<Route path="/home" component={Home} />
<Route path='/home' component={Demo} />
</div>
使用switch:
<div className="panel-body">
{/* 注册路由 */}
<Switch>
<Route path="/about" component={About} />
<Route path="/home" component={Home} />
<Route path='/home' component={Demo} />
</Switch>
</div>