采用 组件化 模式、声明式编码,提高开发效率及组件复用率。
使用虚拟 Dom + 优秀的 Diffing 算法,尽量减少与真实 Dom 的交互。
初始化
基于 create-react-app 搭建
- 全局安装
npm install -g create-react-app - 创建项目
create-react-app my-app - typescript
create-react-app my-app —template typescript - 运行项目
npm start
配置
React-Router
安装 router6.x npm i react-router-dom
引入router
首页用封装的 CreateRouter 组件包裹起来,根据环境变量文件切换 BrowserRouter / HashRouter
// 入口文件组件代码
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import 'animate.css';
import { CreateRouter } from 'router/createRouter';
const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement
);
root.render(
<CreateRouter>
<App />
</CreateRouter>
);
// CreateRouter 组件代码
import { BrowserRouter, HashRouter } from 'react-router-dom';
/**
* 根据环境变量定义,配置路由模式
*
* 路由模式:HTML5({webroot}/xxx/yyy) or HASH({webroot}/#xxx/yyy)
*/
export function CreateRouter({ children }) {
//变量文件
const model = process.env.REACT_APP_HISTORY_MODEL;
if (model === 'HTML5') {
return <BrowserRouter>{children}</BrowserRouter>;
} else {
return <HashRouter>{children}</HashRouter>;
}
}
useRoutes
钩子配置路由
// 创建 router/index.js
import { useRoutes } from 'react-router-dom';
// 引入组件 import { IndexPages } from '../pages/index';
import { Home } from '../pages/home';
import { MyToDo } from '../pages/my-todo';
import { LaunchProcess } from '../pages/launch-process';
const rootRouter = [
{
path: '/',
element: <IndexPages />,
children: [
{
path: '/',
element:<Home/>
},
{
path: '/mytodo',
element:<MyToDo/>
}
]
},
{
path: '/launchProcess',
element:<LaunchProcess/>
}
]
const Router = () => {
const routes = useRoutes(rootRouter) return routes;
}
export default Router;
// App.js 引入
import React from "react";
import Router from "./router";
function App() {
return (
<div className="App">
<Router />
</div>
);
}
export default App;
Outlet
嵌套组件
此组件是一个占位符,告诉 React Router 嵌套的内容应该放到哪里。
import { Outlet } from 'react-router-dom';
// 引入嵌套组件
<Outlet />
useNavigate
跳转、携参
import { useNavigate } from "react-router-dom";
export default function A() {
const navigate = useNavigate();
// 跳转至
navigate('/home')
}
-
push跳转+携带params参数
navigate(/b/child1/${id}/${title}) -
push跳转+携带search参数
navigate(/b/child2?id=${id}&title=${title}) -
push跳转+携带state参数
navigate(“/b/child2”, { state: { id, title }}) -
replace跳转+携带params参数
navigate(/b/child1/${id}/${title},{replace: true}) -
replace跳转+携带search参数
navigate(/b/child2?id=${id}&title=${title},{replace: true}) -
replace跳转+携带state参数
navigate(“/b/child2”, { state: { id, title },replace: true}) -
后退到前一页
navigate(-1) -
后退到前一页的前一页
navigate(-2) -
前向导航
navigate(1)
useParams
获取路由参数的方法
import { useParams } from 'react-router-dom';
export default function Foo(){
const params = useParams();
return (
<div>
<h1>
{params.id}
</h1>
</div>
)
}
useSearchParams
获取seach 参数
import { useSearchParams } from 'react-router-dom';
// 当前路径为 /foo?id=12
function Foo(){
const [searchParams, setSearchParams] = useSearchParams();
console.log(searchParams.get('id')) // 12
setSearchParams({
name: 'foo'
}) // /foo?name=foo
return (
<div>foo</div>
)
}
useLocation
获取传递的state值
- 传递参数
<NavLink to={`detail`} state={{
id:item.id,
name:item.name,
content: item.content }}>
{item.name}
</NavLink>
或
navigate("/b/child2", { state: { id, title }});
- 接收参数
import React from 'react'
import { useLocation } from 'react-router-dom'
export default function Detail() {
// 这是连续结构赋值 把useLocation里面呢的state解构,在解构state里面的属性
const {state:{id,name,content}} = useLocation()
return (
<div>
<ul>
<li>id:{id}</li>
<li>content:{content}</li>
<li>name:{name}</li>
</ul>
</div>
)
}
sass
- 安装与npm对应版本的sass
npm i -D sass
自定义 hook
以 use 开头才能使用 useState、useEffect等 如:useDeviceType
// 动态获取当前设备
export const useDeviceType = () => {
const [device,setDevice] = useState('')
useEffect(() => {
const handler = () => {
if ((navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i))) {
setDevice('mobile')
} else {
setDevice('PC')
}
}
handler()
window.addEventListener('resize', handler)
return () => {
window.removeEventListener('resize',handler)
}
}, [])
return device
}