1.React路由使用的基本
版本
react-router-dom现在发了6.0版本,目前不稳定。
使用步骤
-
安装包。
npm i react-router-dom@5.3.0
这个包提供了三个核心的组件:HashRouter(BrowserRouter), Route, Link
-
导入包,并使用。
import { HashRouter, Route, Link } from 'react-router-dom'
使用HashRouter包裹整个应用,一个项目中只会有一个Router
-
使用Link指定导航链接
-
使用
Route
指定路由规则(哪个路径展示哪个组件)render
和children
展示方式请参考React router 如何渲染(render和children)---访问控制
import React from 'react'
import ReactDom from 'react-dom'
import { HashRouter, Route, Link } from 'react-router-dom'
import Search from './pages/Search.jsx'
import Comment from './pages/Comment.jsx'
export default function App () {
return (
<div>
<h1>react路由基本使用</h1>
<HashRouter>
<Link to="/comment">评论</Link>
<Link to="/search">搜索</Link>
<Route path="/comment" component={Comment} />
<Route path="/search" component={Search} />
</HashRouter>
</div>
)
}
ReactDom.render(<App />, document.getElementById('root'))
2.路由对象-Router
1.Router两种模式
HashRouter :hash模式
BrowserRouter: history模式
2.Router内部原理
Router 组件:包裹整个应用,一个 React 应用只需要使用一次
两种常用 Router:HashRouter
和 BrowserRouter
-
HashRouter:使用 URL 的哈希值实现
- 原理:监听 window 的
hashchange
事件来实现的
- 原理:监听 window 的
-
(推荐)BrowserRouter:使用 H5 的 history.pushState() API 实现
- 原理:监听 window 的
popstate
事件来实现的
- 原理:监听 window 的
3.常规用法
使用es6的导入重命名来统一名字: 无论导入的是哪个路由对象,都叫Router
import { BrowserRouter as Router, Route, Link } from 'react-router-dom'
import { HashRouter as Router, Route, Link } from 'react-router-dom'
3.路由对象Link和NavLink--声明式导航
Link和NavLink都能用来做跳转,最终都会被渲染成<a>内容</a>
标签
import { Link, NavLink } from 'react-router-dom'
1.Link
Link
组件无法展示哪个link处于选中的效果\
<Link to="/search">搜索</Link>
2.NavLink
NavLink
组件,一个更特殊的Link
组件,可以用于指定当前导航高亮
格式:
<NavLink to="/xxx" activeClassName="active">链接</NavLink>
说明:
- to属性,用于指定地址,会渲染成a标签的href属性
- activeClassName: 用于指定高亮的类名,默认
active
。一般不去修改
return (
<div>
<h1>react路由基本使用-Link</h1>
<Router>
<div>
Link:
<Link to="/search">搜索</Link>
<Link to="/comment">评论</Link>
</div>
<div>
NavLink: 自带高亮类
<NavLink to="/" exact>主页</NavLink>
<NavLink to="/search">搜索</NavLink>
<NavLink to="/comment">评论</NavLink>
</div>
<Route path="/comment" component={Comment} />
<Route path="/search" component={Search} />
</Router>
</div>
)
4.路由对象Route
route的作用和格式
- 作用: 决定路由匹配规则
- 格式:
<Route path="/xx/xx" component={组件}></Route>
1.匹配规则
名词约定:
-
path: Route组件中path属性的值
-
pathname: 指的如下格式
- link组件中to的属性值
- 地址栏中的地址
模糊匹配规则
- 只要pathname以path开头就算匹配成功
- 匹配成功就加载对应组件;
- 整个匹配过程是逐一匹配,一个匹配成功了,并不会停止匹配。
模糊匹配和精确匹配
- 默认是模糊匹配的!!!
- 补充exact可以设置成精确匹配
import React from 'react'
import ReactDom from 'react-dom'
import { BrowserRouter as Router, Route, NavLink } from 'react-router-dom'
const Home = () => <div>主页</div>
const Article = () => <div>文章列表页</div>
const ArticleDetail = () => <div>文章详情页</div>
export default function App () {
return (
<div>
<h1>react路由基本使用</h1>
<Router>
// 导航
<NavLink to="/">主页</NavLink>
<NavLink to="/article">文章列表页</NavLink>
<NavLink to="/article/123">文章详情页-123</NavLink>
<hr />
// 对应的跳转规则
<Route path="/" component={Home} />
<Route path="/article" component={Article} />
<Route path="/article/123" component={ArticleDetail} />
</Router>
</div>
)
}
ReactDom.render(<App />, document.getElementById('root'))
2.exact精确匹配
如下代码:
如果不加exact
精确匹配,name所有以'/'开头的都会被这个path匹配到 ,如:'/home' , '/login'
加上exact
精确匹配,只有在path为'/'的时候才能匹配到
<Route path="/" exact component={Home} />
5.Switch
1.用法:
用Switch组件包裹多个Route
组件。
在Switch
组件下,不管有多少个Route的路由规则匹配成功,都只会渲染第一个匹配的组件
import React from 'react'
import ReactDom from 'react-dom'
import {
BrowserRouter as Router,
Route,
NavLink,
Switch
} from 'react-router-dom'
const Home = () => <div>主页</div>
const Article = () => <div>文章列表页</div>
const ArticleDetail = () => <div>文章详情页</div>
export default function App () {
return (
<div>
<h1>react路由基本使用</h1>
<Router>
<NavLink to="/">主页</NavLink>
<NavLink to="/article">文章列表页</NavLink>
<NavLink to="/article/123">文章详情页-123</NavLink>
<hr />
<Switch>
<Route path="/" exact component={Home} />
<Route path="/article" component={Article} />
<Route path="/article/123" component={ArticleDetail} />
</Switch>
</Router>
</div>
)
}
ReactDom.render(<App />, document.getElementById('root'))
2. 404页面处理
通过Switch
组件非常容易的就能实现404错误页面的提示
不设置path属性,将404页对应的路由放在switch内部的最后位置
<Switch>
<Route path="/" exact component={Home} />
<Route path="/article" component={Article} />
<Route path="/article/123" component={ArticleDetail} />
<Route component={Page404} />
</Switch>
6.页面重定向 Redirect
如下代码:
匹配到from = '/'
后 , 重定向到 "/comment"
路径对应的组件
这里的from
页可以改写成path
效果一样
import { HashRouter, Route, Link, Redirect } from 'react-router-dom'
<Redirect from="/" exact to="/comment" />
7.react-router编程式导航
1.history对象
使用格式:
import {useHistory} from 'react-router-dom'
export default function App() {
const history = useHistory()
// 跳转到指定页面
history.push('/home')
// 前进或后退到某个页面,参数 n 表示前进或后退页面数量(比如:-1 表示后退到上一页)
history.go(-1)
// 替换到当前页面,展示指定页面
history.replace('/login')
}
2.history.replace和push的区别
push:向历史记录中添加一条
replace:在历史记录中用目标记录来替换当前记录
示例
push:
详情页 --> login页(push) ----> 主页
此时,从主页后退,会回到login页。 replace
详情页 --> login页(replace) ----> 主页
此时,从主页后退,会回到详情页。
8.路由跳转传参
1.location对象
个人比较喜欢用location
对象和state,search方式获取路由传值的操作,来看下location中有什么:
如何在组件中获取location
对象:
1.组件中的props对象包含了location:
export default function Article (props) {
console.log('props对象', props)
return (
<div>
Article
</div>
)
}
打印结果如图:
2.history中也包含了location对象
import { useHistory } from 'react-router-dom'
export default function Article () {
const history = useHistory()
console.log(history)
return (
<div>
Article
</div>
)
}
打印结果如图:
3.useLocation这个Hook获取
import { useLocation } from 'react-router-dom'
export default function Article () {
const location = useLocation()
console.log('使用useLocation获取的location', location)
return (
<div>
Article
</div>
)
}
打印结果如图:
2.声明式导航的传参:
2.1.查询参数方式:
<Link to= '/home/article ?id=9 '>内容管理</Link>
2.2.对象写法:
// 传递单个id (location.id拿值)
<Link to={{ pathname: '/home/article', id: 3 }}>内容管理</Link>
// 传递id 和 name (location.state拿值)
//这里写的如果不是state:{要传递的参数} ,那么location中原有的state属性会被覆盖,还是使用原有的state吧
<Link to={{ pathname: '/home/article', state: {id:3 , name:'给我一个div'} }}>内容管理</Link>
2.3.接收数据:
再来看看传参之后location
中有什么:
1.查询参数方式:
2.对象写法
2.4.取值:
const value = location.state
const value = location.search
3.编程式导航的传参
同样的用location
,search
,state
message.success('登录成功', 2, () => {
// 做跳转动作 到主页中
history.replace('/home?id=33')
})
const value = location.search
//结果: ?id=33 需要截取一下
message.success('登录成功', 2, () => {
// 做跳转动作 到主页中
history.replace('/home', '给我一个div')
})
const value = location.state
//结果: 给我一个div
message.success('登录成功', 2, () => {
// 做跳转动作 到主页中
history.replace('/home', { name: '给我一个div', id: 9 })
})
const value = location.state
// {name: '给我一个div', id: 9}
4.路由传值小结:
个人比较喜欢这种方式传参,跳转的时候直接给参数,全部在location中接收参数,并且拿到location的方式也很方便
另外还有params方式传参,props对象的match对象中有params对象,函数组件的话也可以使用useParams
钩子
,这里就不介绍了,想补充的兄弟欢迎在下面留言,有不对的地方欢迎指出