单页应用:不刷新,界面局部刷新
前端路由:path-component
后端路由:path-function

借助于BOM中的history,栈结构,默认为push。
push:压栈,出栈
repace:替换栈顶记录
路由组件(Home):this.props={history/location/match}
一般组件(Header):this.props={ }
- import { withRouter } from 'react-router-dom'
-
- // 一般组件没有history属性等,用withRouter函数解决,返回值是一个新组件
- export default withRouter(Header)
-
- console.log(this.props.location.pathname)//地址栏路由
- console.log(this.props.match.path)
- console.log(this.props.match.url)

index.js
BrowserRouter:使用H5的history;兼容性差一点;刷新后state参数还在;用的多
HashRouter:url#后的内容不会发给服务器,兼容性好一点;刷新后state参数不在;解决路径错误问题
- import React from 'react';
- import ReactDOM from 'react-dom/client';
- import App from './App';
- // HashRouter带#
- import { BrowserRouter } from 'react-router-dom';
-
- const root = ReactDOM.createRoot(document.getElementById('root'));
- root.render(
- <React.StrictMode>
- <BrowserRouter>
- <App />
- </BrowserRouter>
- </React.StrictMode>
- );
App.jsx
- import { Route, Link, NavLink, Switch, Redirect } from 'react-router-dom'
-
- 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">
- {/* 1.原生html中,靠<a>跳转不同的页面 */}
- {/* <a className="list-group-item" href="./about.html">About</a> */}
-
- {/* 2.在React中靠路由链接实现切换组件--编写路由链接 */}
- {/*a. 测试模糊匹配(默认) */}
- <Link className="list-group-item" to="/about/a/b">About</Link>
- {/*b. NavLink点击追加高亮类名 */}
- {/* <NavLink activeClassName="demo" className="list-group-item" to="/home">Home</NavLink> */}
- {/*c.封装NavLink,标签体内容Home为children属性;默认为push */}
- <MyLink to="/home">Home</MyLink>
- {/*d.问题:to改为二级路由后刷新:找不到bootstrap文件 ;改为绝对路径:public(React)或者/(常用)*/}
- <MyLink to="/test/demo">测试样式丢失</MyLink>
- </div>
- </div>
- {/* --------展示区-------- */}
- <div className="col-xs-6">
- <div className="panel">
- <div className="panel-body">
- {/* 注册路由:<Switch>组件匹配成功后,不再匹配其他组件。包裹路由组件,提高路由匹配效率 */}
- <Switch>
- {/* exact开启精准匹配,需要再开启。 */}
- <Route path="/about" component={About} exact />
- <Route path="/home" component={Home} />
- <Route path="/home" component={Test} />
- <Route path="/test/demo" component={Test} />
- {/* 匹配不到显示,放到最下面 */}
- <Redirect to="/about" />
- </Switch>
- </div>
- </div>
- </div>
- </div>
- </div>
- )
- }
- }
App.jsx
- import { NavLink, Routes, Route, Navigate, useRoutes } from 'react-router-dom'
- import routes from './routes'
- export default function App () {
- function computedClassName ({ isActive }) {
- return isActive ? 'list-group-item atguigu' : 'list-group-item'
- }
- //根据路由表生成对应的路由规则
- const element = useRoutes(routes)
- return (
- <div>
- <div className="row">
- <Header />
- </div>
- <div className="row">
- <div className="col-xs-2 col-xs-offset-2">
- <div className="list-group">
- {/* 路由链接:className={()=>{}}函数值可以全局定义实现复用*/}
- <NavLink className={computedClassName} to="/about">About</NavLink>
- {/* navLInk的end属性会去掉父级高亮 */}
- <NavLink className={computedClassName} to="/home" end>Home</NavLink>
- </div>
- </div>
- <div className="col-xs-6">
- <div className="panel">
- <div className="panel-body">
- {/* 1.注册路由:Routes包裹Route:path-element ;caseSensitive是否区分大小写 */}
- {/* <Routes>
- <Route path="/About" caseSensitive={false} element={<About />} />
- <Route path="/home" element={<Home />} />
- {/* navigate渲染引起视图切换,包含replace属性 */}
- <Route path="/" element={<Navigate to="/about" />} />
- </Routes> */}
-
- {/* 2.路由表 */}
- {element}
- </div>
- </div>
- </div>
- </div>
- </div>
- )
- }
routes/index.js
- import { Navigate } from 'react-router-dom'
- const arr=[
- {
- path: '/about',
- element:<About/>
- },
- {
- path: '/home',
- element: <Home />,
- children: [//二级路由
- {
- path: 'news',
- element:<News/>
- },
- {
- path: 'message',
- element: <Message />,
- children: [
- //params参数
- // {
- // path: 'detail/:id/:title/:content',
- // element:<Detail/>
- // },
- //search参数
- // {
- // path: 'detail',
- // element:<Detail/>
- // },
- //state参数
- {
- path: 'detail',
- element:<Detail/>
- },
- ]
- }
- ]
- },
- {
- path: '/',
- element:<Navigate to="/about"/>
- },
- ]
- export default arr;

- <div>
- <h3>我是Home的内容</h3>
- {/* 二级路由页面 */}
- <div>
- <ul className="nav nav-tabs">
- <li>
- {/* home组件匹配到了; /home/news组件匹配到了 。 */}
- <MyNavLink to="/home/news">News</MyNavLink>
- </li>
- <li>
- <MyNavLink to="/home/message">Message</MyNavLink>
- </li>
- </ul>
- <Switch>
- <Route path="/home/news" component={News} />
- <Route path="/home/message" component={Message} />
- <Redirect to="/home/news" />
- </Switch>
- </div>
- </div>
- import { Outlet, NavLink } from 'react-router-dom'
- <div>
- <ul className="nav nav-tabs">
- <li>
- <NavLink className="list-group-item" to="news" >News</NavLink>
- </li>
- <li>
- <NavLink className="list-group-item" to="message">Message</NavLink>
- </li>
- </ul>
- {/* 指定路由组件呈现的位置 */}
- <Outlet />
- </div>
刷新后参数不丢,清缓存丢。
携带参数方式:query;params;body(json/urlencoded)

- //路由链接
- <Link to={`/home/message/detail/${item.id}/${item.title}`}>{item.title}</Link>
-
- //注册路由
- <Route path="/home/message/detail/:id/:title" component={Detail} />
-
- //接收
- const { id, title } = this.props.match.params
- import qs from 'querystring'
-
- <Link to={`/home/message/detail/?id=${item.id}&title=${item.title}`}>{item.title}</Link>
-
- <Route path="/home/message/detail" component={Detail} />
-
- //接收
- const { search } = this.props.location
- console.log(search, 'search参数')//?id=1&title=消息1
- const { id, title } = qs.parse(search.slice(1))
-
- //扩展
- let obj = { name: 'tom', age: 18 }
- console.log(qs.stringify(obj))//name=tom&age=18
- let str = 'name=ming&age=19'
- console.log(qs.parse(str))//{name: 'ming', age: '19'}
- <Link to={{ pathname: '/home/message/detail', state: { id: item.id, title: item.title } }}>{item.title}</Link>
-
- <Route path="/home/message/detail" component={Detail} />
-
- //接收
- const { id, title } = this.props.location.state || {}
- import { useParams, useMatch } from 'react-router-dom'
-
- <Link to={`detail/${item.id}/${item.title}/${item.content}`}>{item.title}</Link>
-
- // 方式一:
- const { id, title, content } = useParams()
- // 方式二:
- const x = useMatch('/home/message/detail/:id/:title/:content')
- console.log(x.params);//{id: '2', title: '消息2', content: '2222内容'}
- import { useSearchParams, useLocation} from 'react-router-dom'
-
- <Link to={`detail?id=${item.id}&title=${item.title}&content=${item.content}`}>{item.title}</Link>
-
- // 方式一:
- const [search, setSearch] = useSearchParams();
- const id = search.get('id');
- const title = search.get('title');
- const content = search.get('content');
- {/* <button onClick={() => { setSearch('id=0&title=haha&content=xixi') }}>更新search参数</button> */}
- // 方式二:
- const x = useLocation()
- console.log(x.search)//?id=1&title=%E6%B6%88%E6%81%AF1&content=1111%E5%86%85%E5%AE%B9
- import { useLocation } from 'react-router-dom'
-
- <Link to="detail" state={{ id: item.id, title: item.title, content: item.content }}>{item.title}</Link>
-
- // 方式一:
- const { state: { id, title, content } } = useLocation()

- //push跳转+携带params参数
- this.props.history.push(`/home/message/detail/${id}/${title}`)
- //push跳转+携带search参数
- this.props.history.push(`/home/message/detail?id=${id}&title=${title}`)
- //push跳转+携带state参数
- this.props.history.push(`/home/message/detail/`, { id, title })
-
- this.props.history.replace(`/home/message/detail/`, { id, title })
-
- this.props.history.goBack()
-
- this.props.history.goForward()
-
- this.props.history.go(-1)
- import { useNavigate } from 'react-router-dom'
-
- const navigate = useNavigate()
- navigate(`detail/${item.id}/${item.title}/${item.content}`, {
- replace: false,
- })
-
- navigate(`detail?id=${item.id}&title=${item.title}&content=${item.content}`, {
- replace: false,
- })
-
- navigate('detail', {
- replace: false,
- state: {
- id: item.id, title: item.title, content: item.content
- }
- })
-
- navigate(-1)
-
- navigate(1)
- import { useNavigationType, useResolvedPath,useInRouterContext,useOutlet } from 'react-router-dom'
-
- // push/replace/pop(怎么来的当前页面?刷新!)
- console.log(useNavigationType())
-
- // 给定一个 URL值,解析其中的:path、search、hash值。
- console.log(useResolvedPath('/user?id=001&name=tom#qwe'))//{pathname: '/user', search: '?id=001&name=tom', hash: '#qwe'}
-
- //被BrowserRouter包裹返回true
- const navigate = useInRouterContext()
- console.log(navigate)
-
- // 返回什么???
- console.log(useOutlet(), 'useOutlet')