创建官方React脚手架地址
目录展示
- img
npm 和 npx区别
版本渲染方式差异:
- 17版本之前
- 17版本以后
reactDOM 是react 网页开发的一个类库
使用<React.StrictMode />会导致useEffect()多次执行
在脚手架当中才能这样使用闭合标签<App />\
react-router路由官方文档
- url:reactrouter.com/
npm install react-router-dom
React-Router的使用
- 首要问题就是:
- 1 如何配置
- 2 如何跳转
- 3 如何传参或获取参数
路由配置方式:
第一种 使用 RouterProvider 目前官方推荐的方式
在router/index.js
//引入路由API
import {
createBrowserRouter,
RouterProvider,
useNavigate
} from "react-router-dom";
import { useEffect } from "react";
在router/index.js
// 自己声明了一个 重定向组件
const Redirect = ()=>{
const navigate = useNavigate()
//组件挂载时进行挂载
useEffect(()=>{
navigate('/index')
},[])
return <List />
}
//创建路由
const router = createBrowserRouter([
{
path: "/",
element: <Layout/>,
//子路由
children:[
{
path:'index',
element:<List />
},
{
path:'list',
element:<About/>
},
{
path:'/',
element:<Redirect />
},
]new
},ew
{
path: "/new",
element: <New/>,
},
{
path: "/about",
element: <About/>,
},
//使用params 动态参数
{
path: "/detail/:id",
element: <Detail />,
},
//404路由
{
path:'*',
element:<div>404</div>
}
]);
在index.js
const root = ReactDOM.createRoot(document.getElementById('root'));
//使用RouterProvider来加载路由对象
root.render( <RouterProvider router={router} />)
第二种方式 使用 BrowserRouter 或者 HashRouter组件 (目前应用最广泛的)
在index.js
//引入路由API
import {
BrowserRouter as Router, //用于浏览器路由模式 历史记录模式
HashRouter, //用于切换路由模式 哈希模式
Routes,
Route,
Navigate,
} from "react-router-dom";
在index.js
// 使用路由来渲染根组件 BrowserRouter 或 HashRouter 来配置路由 配置方式2
<Router>
<Routes>
<Route path='/' element={<Layout />}>
<Route path='home' element={<Home />}></Route>
<Route path='new' element={<New />}></Route>
<Route path='/' element={<Navigate to='home'></Navigate>}></Route> //重定向路由配置
</Route>
<Route path='/about' element={<About />}></Route>
<Route path='*' element={<div >404</div>}></Route>
</Routes>
</Router >
第三种方式 使用路由来渲染根组件 useRoute 来配置路由 配置方式3
在index.js
import {
BrowserRouter,
HashRouter as Router,
} from "react-router-dom";
const RootApp = ()=>{
const router = [
{ path:'/' ,
element: <Layout /> ,
children:[
{
path: "index",
element: <Home />
},
{
path: "list",
element: <List />,
},
{
path: '/',
element: <Navigate to='home'></Navigate> //重定向配置
},
]
},
]
const element = useRoutes(router);
return element;
}
const root = ReactDOM.createRoot(document.getElementById('root'));
//使用Router来加载路由对象
root.render( <Router><RootApp></RootApp></Router>)
路由的跳转
页面之间的跳转
- 类似于Vue
- 声明式导航
import { Link } from 'react-router-dom'
<!-- 普通跳转 -->
<Link to="要跳转的页面的path"> 文字提示</Link>
<!-- 替换跳转 -->
<Link to="要跳转的页面的path" replace> 文字提示</Link>
<!-- 跳转会触发整个页面的重新加载(跳转之后刷新) -->
<Link to="要跳转的页面的path" reloadDocument> 文字提示</Link>
使用hook来实现 编程式导航 仅支持函数式组件
- 编程式导航
import { useNavigate } from 'react-router-dom'
const navigate = useNavigate();
navigate('/list') // 普通跳转
navigate('/list',{ replace:true }) // 替换跳转
视图出口
- 类似于Vue
<Router-View />
import { Link, Outlet } from 'react-router-dom'
<div className="ct">
{/* 子路由渲染的内容 */}
{/* Outlet会挂载当前路由匹配路径的子路由 */}
<Outlet></Outlet>
</div>
参数的获取
- 这里是基于函数组件的获取参数。类组件不能使用hook
useLocation
获取query
- 通过useLocation可以获取一个url信息的对象 当中包含有一个search ==> ?后的传参(query传参)。通过原生js URLSearchParams来处理这个字符串来获取参数。
const New = () => {
//location 包含一个search 得到query参数
const location = useLocation()
//通过原生JS URLSearchParams()
const searchParams = new URLSearchParams(location.search)
useEffect(() => {
console.log('location', location);
console.log('sp', searchParams.entries);
const a = searchParams.get('a')
const b = searchParams.get('b')
console.log('a', a);
console.log('b', b);
}, [])
获取state
- useLocation 得到的location 也会得到跳转的时候传递的 state参数
- state参数 可以传递原生的js的数据类型
- state参数一定是在页面之间跳转的时候进行传递的。新打开的时候是获取不到的。(确认一些参数如果是持续存在的 尽量不要使用state来传递)
<Link to='/new/555?a=1&b=2' replace state={{ k: 1, f: 2, j: true, g: [1, 2, 3], l: { o: 2 } }}>to new</Link>
useSearchParams
- 它与useLocation功能相似,就是比useLocation多执行了两步,把useLocation得到的search传入URLSearchParams(),并且返回一个URLSearchParams对象,我们就可以调用里面的方法,完成我们业务需求
const New = () => {
const [query, setQuery] = useSearchParams()
useEffect(() => {
console.log('query',query);
const a = query.get('a')
const b = query.get('b')
console.log('a', a);
console.log('b', b);
}, [])
}
自定义hook
- 考虑到以后业务当中多次使用,进行封装
import { useLocation } from "react-router-dom";
export const useQuery = ()=>{
const location = useLocation()
const searchParams = new URLSearchParams(location.search)
const newObj = {}
for (let [key, value] in searchParams.entries) {
newObj[key] = value
}
return newObj
//最终是返回query方式传参的参数 以{key:value}形式返回
}
useParams
获取params
- 用于获取传递的params参数
const New = () => {
const params = useParams()
useEffect(() => {
console.log('queryObj', queryObj);
console.log('params', params);
}, [])
}
类组件获取查询参数
- 这里利用的是高阶组件的特性,对属性进行劫持,也就是在使用传入组件的同时携带一些新参数,并且以新组件的形式返回
- 高阶组件:是一个函数,参数是传入一个组件,并且返回一个新的组件
import { useLocation,useSearchParams ,useParams } from "react-router-dom";
//上一个自定义hook
import { useQuery } from "./qf";
const withRouter = (Cp)=>{
//高阶组件是函数不能使用hook
// 返回一个函数组件
return (props)=>{
// 利用函数组件可以使用 hooks的特性 先通过react-router-dom中
// 的useLocation 来获取location对象
const location = useLocation();
const params = useParams();
const query = useQuery()
return ( <Cp
location={location}
params={params}
query={query}
//{...props} 让原来组件保持原有的属性
{...props} />)
}
}
// 通过withRouter来包裹组件 从而通过这个HOC可以让 类组件获取路由信息
export default withRouter
参数的传递
params参数
- 需要在路由表当中进行配置,例如:
{
path: 'new/:id',
element: <New />
},
query参数
- 查询参数只需在跳转的时候,在url后面以
?key=val&key1=val1进行拼接