前言
早期多个页面借助a标签实现路由的跳转,也就是多页面编程,n个导航对应n个html.而且点击链接后,整个页面会刷新,页面会跳转-如果需据会发送请求获取数据。react是单页面多组件应用,链接称为路由链接,点击后,会全局更新,也就是局部刷新,并且不会像发送请求,这里是说这个请求并不是因为你点击链接产生的,组件中的数据还是需要请求的。而点击产生的路径与渲染组件的对应关系取决于react-router插件库了。
SPA
- 单页Web应用(single page web application,SPA)。
- 整个应用只有一个完整的页面。
- 点击页面中的链接不会刷新页面,只会做页面的**局部更新。
数据都需要通过ajax请求获取, 并在前端异步展现。
1. 路由的理解
1. 什么是路由?
- 一个路由就是一个映射关系(key:value)
- key为路径, value可能是function或component
2. 路由分类
后端路由:
- 理解: value是function, 用来处理客户端提交的请求。
- 注册路由: router.get(path, function(req, res))
/* 请求地址: http://localhost:3000/search/users?q=aa 后台路由 key: /search/users value: function () {} */ app.get("/search/users", function (req, res) { const {q} = req.query axios({ url: 'https://api.github.com/search/users', params: {q} }).then(response => { res.json(response.data) }) })
- 工作过程:当node接收到一个请求时, 根据请求路径找到匹配的路由, 调用路由中的函数来处理请求, 返回响应数据
前端路由:浏览器端路由
- 理解: value是component,用于展示页面内容
注册路由:
<Route path="/test" component={Test}>
- 工作过程:当浏览器的path变为/test时(路由链接可以直接修改浏览器地址), 当前路由组件就会变为Test组件
3. 路由工作原理
、
这是典型的多页面应用,点击导航区切换,请求另一个页面,展示区是变了。会跳转到另一个页面,并且会刷新,多个展示区需要多个html。
原理:
- 一开始的地址栏是没有参数的,127.0.0.1/ ,没有多页面应用的xxx.html的后缀(.html 代表一个页面o)
- 点击路由链接后,路由会修改浏览器的地址,127.0.0.1/ home/ 页面并不会发生跳转。【区别于a链接 点击后不跳转】
- 路由中检测浏览器的路径(参数)变化(这里是会忽略前面的ip 以及port)匹配组件参数,展示相应的组件
路由监测的实现: 得益于history对象 浏览器历史记录
点击导航区,路径改变 === 路径改变,被检测 === 匹配组件,展示区变化。
为什么点击路由链接后地址栏会变路径呢?谁监测路径的变化呢?
依靠浏览器的历史记录 history对象
我们一般不会直接去操作这个window.history 去操作浏览器的路径 历史记录的修改以及替换 因为原生的api不好用 so
借助一个库history.js 这个创建的history对象本质也是操作了bom的history
history.push/forward/go/back/replace
两种路由模式: history: hash(# 兼容性好) browser
2. react-router-dom的理解
- react-router 插件库其实有三种实现 适用于三种平台 web(dom) native(原生) anywhere(通用性强 api 过多)
- react的一个插件库。本质是react写的,依赖于react才可以工作。
- 专门用来实现一个SPA应用
- 基于react的项目基本都会用到此库。
router: 路由器 管理路由
route: 路由(接口 天线)
原生写react
1.复杂需要多个html 引入各种react文件 编码慢
2.通过js修改为jsx的形式依靠浏览器babel 翻译 代码过多浏览器忙不过来
3. 使用cli 简单快速搭建react 应用 cli是webpeck 搭建的,他有好多loader plugins 由很多功能‘
4.安装脚手架 create-react-app库帮助你安装cli
5.创建项目 create-react-app 项目名
6.启动 npm start
webpeck 官方把关于react的配置文件隐藏了 执行eject 会暴露处所有的配置文件并且回不去了
7.react中不建议使用jquery 因为他注重的是操作原生dom。而 react是不关注视图层的
axios: 轻量 可运行在服务端 支持promise 本质就是xmlHttpRequest对象的封装
3. react-router-dom相关API
3.1. 内置组件
<BrowserRouter>
路由器 管理路由 一个应用只有一个路由器。
<BrowserRouter> <App/> </BrowserRouter>
<HashRouter>
- 路由器 管理路由。
<Route>
作用:注册路由 匹配组件 path 路径 components 组件
<Route path="/about" component={About}/>
<Redirect>
1.一般写在所有路由注册的最下方,当所有路由都无法匹配时,跳转到Redirect指定的路由 2.具体编码: <Switch> <Route path="/about" component={About}/> <Route path="/home" component={Home}/> <Redirect to="/about"/> </Switch> Redirect是值得匹配不到后,显示的组件,就是最后承担者,兜底的人。
<Link>
路由链接link 本质是a标签 作用就是点击后修改地址栏路径 浏览器的历史记录就会工作 当路径变化就会匹配组件 <a href="./home.html">Home</a> ===> <Link to="/home">Home</Link> 使用方式与a链接一样,只是href的值是具体的网页地址,to的属性值是路径参数(没有点) Link需要被路由器所管理,这个路由器需要具体,hash / browser,link 可以实现浏览器的路径变化以及历史记录的添加
<NavLink>
点击时路由链接高亮的效果,点击时给链接动态的追加一个类class=active 由于boot里面active恰好是高亮 可设置 activeClassName 属性 制定选中后的类名 注意boot里面样式权重大,因为boot默认会给点击的添加active类,导致你有两个类。??可是为什么闪烁你写的需要important
组件标签体就是标签的children属性 值可通过this.prop.children获取
<Switch>
<MyNavLink to="/about">About</MyNavLink> <MyNavLink to="/home">Home</MyNavLink> /* 制定浏览器路径以及浏览器的历史记录 */ <Route path="/about" component={About}/> <Route path="/home" component={Home}/> <Route path="/home" component={Test}/> /* 匹配路径 显示组件 会发现都展示了 如果注册的路由特别多,他会一直匹配,只要满足就显示,效率低下 */
1. 通常情况下,path和component是一一对应的关系。 2. Switch可以提高路由匹配效率(单一匹配) 匹配一个后不会继续匹配了。
3.2. 其它
- history对象
- match对象
- withRouter函数
4. 路由使用
1.明确好界面中的导航区、展示区
2.导航区的a标签改为Link标签
<Link to="/xxxxx">Demo</Link>
3.展示区写Route标签进行路径的匹配
<Route path='/xxxx' component={Demo}/>
4.<App>的最外侧包裹了一个<BrowserRouter>或<HashRouter>
4.1 路由组件与一般组件
1.写法不同:
一般组件:<Demo/>
路由组件:<Route path="/demo" component={Demo}/>
2.存放位置不同:
一般组件:components
路由组件:pages
3.接收到的props不同:
一般组件:写组件标签时传递了什么,就能收到什么
路由组件:接收到三个固定的属性
history:
go: ƒ go(n)
goBack: ƒ goBack()
goForward: ƒ goForward()
listen:f listen(listenr)
push: ƒ push(path, state)
replace: ƒ replace(path, state)
location: history.location === location
location:
pathname: "/about"
search: ""
state: undefined
match:
isExact: true 是否精准匹配
params: {}
path: "/about"
url: "/about"
4.2 样式丢失
1.public/index.html 中 引入样式时不写 ./ 写 / (常用)
2.public/index.html 中 引入样式时不写 ./ 写 %PUBLIC_URL% (常用)
3.使用HashRouter
4.3 路由的严格匹配与模糊匹配
<MyNavLink to="/home/a/b">Home</MyNavLink>
<Route path="/home" component={Home}/>
拿出 home a b 与home可以匹配 给的多是可以的
1.默认使用的是模糊匹配(简单记:【输入的路径】必须包含要【匹配的路径】,且顺序要一致)
2.开启严格匹配:<Route exact={true} path="/about" component={About}/>
3.严格匹配不要随便开启,需要再开,有些时候开启会导致无法继续匹配二级路由
4.4 开启repalce模式
<Link repalce to="/xxxxx">Demo</Link> 替换模式
4.5 withRouter
export default withRouter(Header)
Header组件的props里就有history了
withRouter可以加工一般组件,让一般组件具备路由组件所特有的API
withRouter的返回值是一个新组件
5. 嵌套路由使用
1.注册子路由时要写上父路由的path值
2.路由的匹配是按照注册路由的顺序进行的
6. 向路由组件传递参数数据
1.params参数
路由链接(携带参数):<Link to='/demo/test/tom/18'}>详情</Link>
注册路由(声明接收):<Route path="/demo/test/:name/:age" component={Test}/>
接收参数:this.props.match.params
2.search参数
路由链接(携带参数):<Link to='/demo/test?name=tom&age=18'}>详情</Link>
注册路由(无需声明,正常注册即可):<Route path="/demo/test" component={Test}/>
接收参数:this.props.location.search
备注:获取到的search是urlencoded编码字符串,需要借助querystring解析
3.state参数
路由链接(携带参数):<Link to={{pathname:'/demo/test',state:{name:'tom',age:18}}}>详情</Link>
注册路由(无需声明,正常注册即可):<Route path="/demo/test" component={Test}/>
接收参数:this.props.location.state
备注:刷新也可以保留住参数
7. 多种路由跳转方式
借助this.prosp.history对象上的API对操作路由跳转、前进、后退
-this.prosp.history.push()
-this.prosp.history.replace()
-this.prosp.history.goBack()
-this.prosp.history.goForward()
-this.prosp.history.go()
8. BrowserRouter与HashRouter的区别
1.底层原理不一样:
BrowserRouter使用的是H5的history API,不兼容IE9及以下版本。
HashRouter使用的是URL的哈希值。
2.path表现形式不一样
BrowserRouter的路径中没有#,例如:localhost:3000/demo/test
HashRouter的路径包含#,例如:localhost:3000/#/demo/test
3.刷新后对路由state参数的影响
(1).BrowserRouter没有任何影响,因为state保存在history对象中。
(2).HashRouter刷新后会导致路由state参数的丢失!!!
4.备注:HashRouter可以用于解决一些路径错误相关的问题。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。