监听 URL 的变化,当 URL 变更时,它将使浏览器显示相应的页面
所以需要包裹在需要使用组件路由的最外层
import ReactDOM from 'react-dom';
import { BrowserRouter, Route, Routes, Link } from 'react-router-dom'
function App() {
return (
// 1.最外层必须使用BrowserRouter或者HashRouter包裹,
<BrowserRouter>
...
</BrowserRouter>
);
}
HashRouter
使用window.location.hash 属性和window.onhashchange事件
可以监听浏览器hash值得变化,去执行相应的js切换网页
hash路由实现原理:
hash 指的是地址中 #
号以及后面的字符,称为散列值
散列值不会随请求发送到服务器端的,所以改变hash,不会重新加载界面
监听onhashchange事件,hash改变时,可以通过window.location.hash来获取和设置hash值
location.hash值的变化直接反应在浏览器的地址栏
BrowserRouter
使用history首先应该了解window.history对象
它表示的是当前窗口的浏览历史,当发生改变时,只会改变路径,不会刷新界面
History对象就是一个堆栈
<Link to="/login">....</Link>
默认类名
点击之后,会显示高亮,高亮的默认类名是active
,我们只需要编写一个类名为active
的css样式即可
.active {
background-color:red;
}
特定类名
如果高亮的类名不是active,则需要使用<NavLink to='xx' className={函数}>
这种写法
function computedClassName({ isActive }) {
// setActives表示高亮的类名,也就是选中的样式,normal表示未选中的样式
// isActive为true则表示选中
return isActive ? 'setActives' : 'normal'
}
<NavLink to='/login' className={computedClassName}>login组件</NavLink>
<a></a>
跳转依靠的是href
属性
NavLink
跳转依靠的是to
属性
作用:只要<Navigate>
组件被渲染,就会修改路径,切换视图
<Navigate to='/路径'/>
<Navigate replace>
replace表示跳转模式,默认是false,表示push,如果为true,表示replaceimport ReactDOM from 'react-dom';
import { BrowserRouter, Route, Routes, Navigate } from 'react-router-dom'
function App() {
return (
<BrowserRouter>
<Routes>
{/* 一开始进入页面路径是'/',我们重定向到/home页面 */}
<Route path='/' element={<Navigate to='/home' />} />
<Route path='/home' element={<Home />} />
</Routes>
</BrowserRouter>
);
}
function Home() {
return <div>home组件</div>
}
ReactDOM.render(<App />, document.getElementById('root'))
<Routes>
<Route path='/login' element={<Login/>} />
<Route path='/home' element={<Home />} />
</Routes>
<Route>
组件必须被<Routes>
组件包裹
<Routes>
内匹配到一个<Route>
之后,就不会继续向下匹配了
<Route caseSensitive>
属性用于指定:匹配是否区分大小写(默认为false)
其实在实际开发中,我们如果总是用这种写法
<Routes><Route path='/Home' element={<Home />} /></Routes>
进行开发每次使用Route都要包裹一个Routes是比较麻烦的,因此就有了我们的路由表useRoutes()
我们使用路由表对路由进行统一管理
一般在src
文件夹下创建routes
文件夹,并在其中编写路由
语法:const element=useRoutes([{path:'路径',element:'组件',children:'子路由'}])
例子:
// 路由表
import About from '../page/About'
import Home from '../pages/Home'
export default [
{
path:'/about',
element:<About/>
},{
path:'/home',
element:<Home/>
}
]
import {useRoutes} from 'react-router-dom'
import routes from './routes'
// 路由表的使用
function App(){
const element = UseRoutes(routes)
return (
{element}
)
}
子路由不用写全路径
比如:
父路由:
/home
子路由:
/home/news
、/home/messages
path:'/home', element:<Home/>, children:[ { path:'new', element:<news/> },{ path:'messages', element:<messages/> } ]
import ReactDOM from 'react-dom';
import { BrowserRouter, Link, useRoutes, Navigate, Outlet } from 'react-router-dom'
function App() {
const element = useRoutes([
{
path: '/home', element: <Home />, children: [
{
path: 'news',
element: <News />
}
]
},
{ path: '/', element: <Navigate to='/home' /> },
])
// 在路由区直接使用{element},不需要写`<Routes><Route></Route></Routes>`
return <div>{ element }</div>
}
function Home() {
return <div>home组件
<Link to='news'>跳转到new组件</Link>
{/* 因为是home的子组件,所以在这里使用<Outlet>组件, */}
<Outlet />
</div>
}
function News() {
return <div>news组件</div>
}
ReactDOM.render(<BrowserRouter><App /></BrowserRouter>, document.getElementById('root'))
路由添加占位符
path:'detail/:id/:title/:content'
跳转传递参数
<Link to={`detail/${id}/${title}/${content}`}></Link>
接收参数
import {useParams} from 'react-router-dom'
function Detail(){
const {id,title,content} = useParams()
return (
<ul>
<li>{id}</li>
<li>{title}</li>
<li>{content}</li>
</ul>
)
}
路由跳转传递参数
<Link to={`detail?id=${id}&title=${title}&content=${content}`}></Link>
接收参数
import {useSearchParams} from 'react-router-dom'
function Detail(){
const [search,setSearch] = useSearchParams()
// 获取参数
const id = search.get('id')
const title = search.get('title')
}
setSearch
用于修改传递的参数,使用得较少
<button onClick={() => setSearch('id=465&title=哈哈&content=呵呵')}>更新</button>
传递参数
<Link
to="detail"
state={{
id:m.id,
title:m.title,
content:m.content
}}
></Link>
接收参数
import {useLocation} from 'react-router-dom'
const {state:{id,title,content}} = useLocation()
const navigate = useNavigate();
navigate('/跳转路径',{replace:跳转模式(push或者replace,默认是push),state:{参数}})
navigate(-1)
:后退一步,navigate(1)
:前进一步
import ReactDOM from 'react-dom';
import { BrowserRouter, useRoutes, Navigate,useNavigate } from 'react-router-dom'
function App() {
const element = useRoutes([
{ path: '/home', element: <Home /> },
{ path: '/news', element: <News /> },
{ path: '/', element: <Navigate to='/home' /> },
])
return <div>{element}</div>
}
function Home() {
const navigate=useNavigate()
function handleClick(){
navigate('/news')
}
return <button onClick={handleClick}>跳转到new组件</button>
}
function News() {
return <div>news组件</div>
}
ReactDOM.render(<BrowserRouter><App /></BrowserRouter>, document.getElementById('root'))