1、SPA应用的理解
1、单页Web应用(single page web application,SPA)。
2、整个应用只有一个完整的页面。
3、点击页面中的链接 不会刷新 页面,只会做页面的 局部更新。
4、数据都需要通过ajax请求获取, 并在前端异步展现。
2、路由
- 什么是路由???
1.一个路由就是一个映射关系(key:value) 2.key为路径, value可能是function或component
- 路由的分类
- 后端路由
1)理解: value是function, 用来处理客户端提交的请求。 2)注册路由: router.get(path, function(req, res)) 3)工作过程:当node接收到一个请求时, 根据请求路径找到匹配的路由, 调用路由中的函数来处理请求, 返回响应数据
- 前端路由
1)浏览器端路由,value是component,用于展示页面内容。 2)注册路由: <Route path="/test" component={Test}> 3)工作过程:当浏览器的path变为/test时, 当前路由组件就会变为Test组件
- 后端路由
- 路由实现:参考之前写过的文章,地址为:https://www.cnblogs.com/wxh0929/p/15049790.html
3、react-router-dom
- 插件的安装:目前安装的版本为5.3.0
cnpm i react-router-dom -S
- 路由组件与一般组件的区别
1、写法不同 一般组件:<Home /> 路由组件:<Route path="/home" component={Home}></Route> 2、存放位置不同 一般组件:components 路由组件:pages 3、接收到的props不同 一般组件:组件标签传递了什么,就能收到什么 路由组件:接收到三个固定的属性
- 基本路由的使用
- 效果
-
- 示例
- 导航区的a标签改为Link标签,用于编写路由链接
{/* 原生html中,靠a标签跳转不同的页面 */} {/* <a className="list-group-item" href="./about.html">About</a> <a className="list-group-item active" href="./home.html">Home</a> */} {/* 在React中,靠路由链接实现切换组件 ----- 编写路由链接 Router是指路由器*/} <Router> <Link className="list-group-item" to="/about">About</Link> <Link className="list-group-item" to="/home">Home</Link> </Router>
- 展示区写Route标签进行路径的匹配注册路由
{/* 注册路由 */} <Router> <Route path="/about" component={About}></Route> <Route path="/home" component={Home}></Route> </Router>
现象:点击导航栏时内容无法更新,这是因为一个应用只能使用一个路由器来管理,解决方法是,在入口文件index.js中使用一个路由器管理App组件
import React from "react"; import ReactDOM from "react-dom"; import { BrowserRouter as Router } from "react-router-dom"; import App from "./App"; ReactDOM.render( <Router> <App /> </Router>, document.getElementById("root") );
{/* 在React中,靠路由链接实现切换组件 ----- 编写路由链接*/} <Link className="list-group-item" to="/about">About</Link> <Link className="list-group-item" to="/home">Home</Link> {/* 注册路由 */} <Route path="/about" component={About}></Route> <Route path="/home" component={Home}></Route>
- 当你的路由链接想动态添加class属性实现高亮的时候,使用NavLink
{/* NavLink用于被选中的时候添加类名,类名默认为 active */} <NavLink className="list-group-item" to="/about">About</NavLink> <NavLink className="list-group-item" to="/home">Home</NavLink> {/* 更改路由选中后的类名,由于使用的是bootstrap的样式,会出现闪烁现象,因此设置样式需给最高权重 */} <NavLink activeClassName="side_link" className="list-group-item" to="/about">About</NavLink> <NavLink activeClassName="side_link" className="list-group-item" to="/home">Home</NavLink> {/* 设置路由选中的行间样式 */} <NavLink activeStyle={{backgroundColor:'orange'}} className="list-group-item" to="/about">About</NavLink> <NavLink activeStyle={{backgroundColor:'orange'}} className="list-group-item" to="/home">Home</NavLink>
- NavLink的封装
import React, { Component } from 'react' import {NavLink} from 'react-router-dom' export default class MyNavLink extends Component { // 标签体内容是一个特殊的标签属性,通过this.props.children可以获取标签体内容 render() { return ( <NavLink activeClassName="side_link" className="list-group-item" {...this.props} /> ) } }
例子:
<MyNavLink to="/about">About</MyNavLink>
- NavLink的封装
- 导航区的a标签改为Link标签,用于编写路由链接
- Switch的使用
- 通常情况下,path和component是一一对应的关系,但是当一个path匹配多个component时,多个组件都会同时展示,例如
<Route path="/home" component={About}></Route> <Route path="/home" component={Home}></Route>
现象:
解决方法:Switch组件包裹你注册的所有路由,那么只会匹配一个路由的组件,不会继续向后匹配(Switch可以提高路由匹配效率,即单一匹配)
<Switch> <Route path="/home" component={About}></Route> <Route path="/home" component={Home}></Route> </Switch>
- 通常情况下,path和component是一一对应的关系,但是当一个path匹配多个component时,多个组件都会同时展示,例如
- 路由的模糊匹配与严格匹配
// 默认使用的是模糊匹配,(简单记:【输入的路径to】必须包含要【匹配的路径path】 // 且【顺序要一致】,如果to="a/home/b" path="/home",则无法匹配,to="/home/a/b" path="/home" ,则可以匹配) <MyNavLink to="/home/a/b">Home</MyNavLink> <Route path="/home" component={Home}></Route> // 解决:开启严格匹配,但是严格匹配不要随便开启,需要再开,有些时候开启会导致无法继续匹配二级路由 <Route exact path="/home" component={Home}></Route>
- 路由的重定向
- 示例
- 嵌套路由(二级路由)的使用
- 注意:
1、注册子路由时要写上父路由的path值; 2、路由的匹配是按照注册路由的顺序进行的;
- 注意:
-
- 路由组件传递参数
- 第一种方式:params(http://localhost:3000/home/message/detail/003/%E6%B6%88%E6%81%AF3) 注意:必须要传,否则进不去
1、路由链接(携带参数) {/* 向路由组件传递params参数 */} <Link to={`/home/message/detail/${el.id}/${el.title}`}>{el.title}</Link> 2、注册路由(声明接收) <Route path="/home/message/detail/:id/:title" component={Detail}></Route> 3、接收参数 let { id, title } = this.props.match.params;
- 第二种方式:search/query(http://localhost:3000/home/message/detail/?id=002&title=%E6%B6%88%E6%81%AF2)注意:不传值也可以进去
1、路由链接(携带参数) {/* 向路由组件传递search参数 */} <Link to={`/home/message/detail/?id=${el.id}&title=${el.title}`}>{el.title}</Link> 2、注册路由(search参数无需声明接收,正常注册路由即可) <Route path="/home/message/detail" component={Detail}></Route> 3、接收参数 import qs from 'querystring' //无需安装,react内置 //备注;获取到的search是urlencoded编码字符串,使用qs进行解析,它的parse方法能解析key=value&key=value的字符串 let {id,title} = qs.parse(this.props.location.search.slice("1"))
- 第三种方式:state(http://localhost:3000/home/message/detail)
1、路由链接(携带参数) {/* 向路由组件传递state参数 */} <Link to={{pathname:'/home/message/detail',state:{id:el.id,title:el.title}}}>{el.title}</Link> 2、注册路由(state参数无需声明接收,正常注册路由即可) <Route path="/home/message/detail" component={Detail}></Route> 3、接收参数 // 备注:页面刷新后,数据不会丢失,因为BrowserRouter会对history对象进行保存,而location是history的一个参数
// 而HashRouter刷新后会导致路由state参数的丢失 let { id, title } = this.props.location.state || {};
- 第一种方式:params(http://localhost:3000/home/message/detail/003/%E6%B6%88%E6%81%AF3) 注意:必须要传,否则进不去
- 路由组件传递参数
- push与replace模式的区别???
1、react中的路由跳转默认使用的是push模式,即压栈的形式,会留下痕迹; 2、replace模式则是替换模式,即类似于无痕浏览;
- 编程式路由导航:借助this.props.history对象上的API来实现路由的跳转、前进与后退等;
- 使用场景:点击登录按钮登陆成功后,自动跳转到应用的首页,通过JS代码来实现路由跳转;
- 跳转方式
- push跳转
// 1、携带params参数 this.props.history.push(`/home/message/detail/${el.id}/${el.title}`) // 2、携带search参数 this.props.history.push(`/home/message/detail/?id=${el.id}&title=${el.title}`) // 3、携带state参数 this.props.history.push(`/home/message/detail/`,{id:el.id,title:el.title})
- replace跳转
// 1、携带params参数 this.props.history.replace(`/home/message/detail/${el.id}/${el.title}`) // 2、携带search参数 this.props.history.replace(`/home/message/detail/?id=${el.id}&title=${el.title}`) // 3、携带state参数 this.props.history.replace(`/home/message/detail/`,{id:el.id,title:el.title})
- go跳转
// 正数代表前进几步、负数代表后退几步,0代表刷新 this.props.history.go(2)
- 前进
this.props.history.goForward()
- 后退
this.props.history.goBack()
- 如何让一般组件也可以使用编程式路由导航???
import {withRouter} from 'react-router-dom' class Header extends React.Component{} // withRouter可以加工一般组件,让一般组件具备路由组件特有的API,他的返回值是一个新组件 export default withRouter(Header)
- push跳转
4、遇到的问题
- 解决多级路径刷新页面样式丢失的问题
1、public/index.html中,引入样式 不写 ./ 写 / (常用) 2、public/index.html中,引入样式 不写 ./ 写 %PUBLIC_URL%(常用) 3、使用HashRouter