Skip to content

Commit

Permalink
feat: 日常更新
Browse files Browse the repository at this point in the history
  • Loading branch information
pengmao committed Sep 10, 2024
1 parent e1cc4b6 commit 358afa4
Show file tree
Hide file tree
Showing 3 changed files with 288 additions and 1 deletion.
6 changes: 5 additions & 1 deletion docs/.vitepress/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ export default {
text: 'React',
items: [
{ text: 'React', link: '/frontEnd/frame/React/' },
{ text: '深入React', link: '/frontEnd/frame/React/Learn' },
{ text: 'Fiber', link: '/frontEnd/frame/React/Fiber' }
]
},
Expand All @@ -108,7 +109,10 @@ export default {
},
{
text: '其他',
items: [{ text: '表单', link: '/frontEnd/frame/Other/form' }]
items: [
{ text: '表单', link: '/frontEnd/frame/Other/form' },
{ text: '项目搭建', link: '/frontEnd/frame/Other/build' }
]
}
],

Expand Down
190 changes: 190 additions & 0 deletions docs/frontEnd/frame/Other/build.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
# 大型项目搭建

在大型前端应用的开发中,每个模块都需要细化和规范化,以确保系统的可维护性、可扩展性以及开发效率。以下是对前面提到的各个模块的细化说明:

## 模块化和组件化开发

- 组件结构设计:

- 组件分为页面组件(Page Components)和可复用组件(Reusable Components)。
- 页面组件负责布局和业务逻辑,每个页面组件通常对应一个 URL 路径。
- 可复用组件应保持独立性,具备清晰的输入输出(通过 props 和 events 通信)。
- 容器组件(Container Components):负责数据获取和逻辑处理,内部调用展示组件(Presentational Components),展示组件只负责渲染。

- 目录结构设计:

- 根据项目规模,按功能模块划分目录,确保组件的可维护性。
- 一个典型的目录结构:

```scss
src/
├── components/ // 可复用的基础组件
├── pages/ // 页面级别组件
├── services/ // 数据获取和 API 封装
├── store/ // 全局状态管理
├── utils/ // 公共工具函数
├── assets/ // 静态资源
├── hooks/ // 自定义 Hooks
├── styles/ // 全局样式
```

- 代码分割与懒加载:

- 对于大型应用,保持每个组件独立并进行代码分割非常重要。可以利用动态导入的方式懒加载某些组件:

```js
const SomeComponent = React.lazy(() => import('./SomeComponent'))
```

## 状态管理

细粒度状态管理:

- 避免将所有状态都放入全局管理,应该根据应用需求决定哪些状态需要全局共享,哪些只需局部管理。将组件内部状态(如表单输入)与全局状态(如用户信息)分开管理。

Redux的最佳实践:

- 使用Redux Toolkit简化 Redux 的写法。
- 将状态分为不同的slice(切片),每个切片负责管理一个功能模块的状态:

```js
const userSlice = createSlice({
name: 'user',
initialState: { name: '', age: 0 },
reducers: {
setUser(state, action) {
state.name = action.payload.name
state.age = action.payload.age
}
}
})
```

异步状态管理:

- 使用Redux Thunk或Redux Saga管理异步逻辑,确保异步操作(如 API 请求)不会阻塞 UI 渲染。

React Context API 和 Hooks:

- 对于简单的状态管理,可以结合Context API与useReducer或useState来管理局部状态,避免过度依赖 Redux 造成复杂性。

## 路由管理

使用React Router来进行路由搭建。

通过配置的形式来进行路由创建:

```js
export const Routers = [
{
path: '/',
component: lazy(() => import('../layouts/basicLayout')),
children: [
// xxx
]
}
// xxx
]
```

在App组件内通过循环渲染来生成组件:

```jsx
<HistoryRouter history={history} basename={baseName}>
<Routes>
{routers.map(route => {
const Element = route.component
return (
<Route key={route.path} path={route.path} element={<Element />}>
{route.children ? renderRoutes(route.children) : null}
</Route>
)
})}
</Routes>
</HistoryRouter>
```

- 懒加载与按需加载:

- 每个路由组件都可以通过 React.lazy 进行懒加载,提升初始页面加载速度。
- 路由表可以动态生成,支持权限控制,根据用户角色动态加载不同的页面模块。

- 守卫和权限控制:

- 使用高阶组件(HOC)或路由守卫实现页面访问控制。基于用户角色或权限配置,动态跳转或限制某些路由访问。

## 性能优化

- 长列表优化:

- 使用虚拟滚动技术渲染长列表,避免渲染大量 DOM 元素:

```jsx
import { FixedSizeList as List } from 'react-window'
// xxx
;<List height={500} itemCount={1000} itemSize={35}>
{({ index, style }) => <div style={style}>Row {index}</div>}
</List>
```

- 图片优化:

- 图片应使用懒加载,并按需调整大小(使用 CSS 中的 srcset):

```html
<img src="small.jpg" srcset="large.jpg 1024w" alt="image" />
```

- 使用精灵图

- 代码分割:

- 通过 Webpack/Vite 实现代码的动态加载(code splitting),避免一次性加载整个应用的所有代码。

## 构建工具的选择

- Webpack/Vite 配置优化:

- Webpack:通过设置 splitChunks 和 bundle analyzer 进行代码拆分和打包优化。
- Vite:利用 Vite 的热更新和模块预构建功能,提升开发体验和构建速度。

- 生产环境优化:

- 压缩代码、启用 Tree Shaking 删除无用代码、使用 Brotli 或 Gzip 压缩传输静态资源。

## API 管理与数据获取

- API 封装与抽象:

- 将所有 API 请求统一封装成服务模块(service layer),避免在组件中直接调用 fetch 或 axios。

- 提供统一的错误处理和请求拦截:

```js
const axiosInstance = axios.create({ baseURL: '/api' })
axiosInstance.interceptors.response.use(
response => response,
error => Promise.reject(error)
)
```

## CI/CD 集成

- 自动化构建与部署:

- 使用 GitHub Actions 或 Jenkins 配置CI/CD 流水线,自动运行测试和构建,并自动部署到生产环境。

- Lint 检查:

- 在 CI 中集成 ESLint 和 Prettier 检查代码质量,确保代码风格统一。

## 团队协作

- Git 分支管理:

- 使用 Git Flow 或 Trunk-based Development 来管理开发过程中的多个分支,确保功能开发、测试和发布流程的规范性。

- 代码评审和协作工具:

- 借助Code Review工具(如 GitHub、GitLab)进行代码评审,确保代码质量。
- 使用 Jira 或 Trello 来管理任务,确保团队协作有序。
93 changes: 93 additions & 0 deletions docs/frontEnd/frame/React/Learn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# 深入理解React

深入理解 React

## 组件的本质

在 React 中,组件是核心构建单元。组件可以是函数组件或类组件,它们的本质都是 JavaScript 函数或类,接收 props 并返回 UI(通常是 JSX 语法描述的虚拟 DOM)。深入理解组件的渲染和生命周期,可以帮助你优化性能。

关键要点:

- 函数组件 vs 类组件:了解函数组件如何通过 Hooks 管理状态和副作用,并理解类组件的生命周期。
- 无状态组件和有状态组件:无状态组件更容易优化,尽可能使用函数组件和 Hooks。
- 受控组件和非受控组件:掌控表单处理时,使用受控组件能更精确地控制表单的状态。

首先讲讲这个类组件。在`React`17.x,也就是`hooks`出现之前,只有类组件才有状态state这个`概念`,函数组件就是一个纯函数,纯函数即是`相同的输入得到相同的输出的这一类函数`,因此函数组件无法做到有状态。

要做到有状态就需要类组件。类组件被设计如下进行状态管理,state即使这个组件的状态,通过`this.setState`来修改状态,并触发组件重新渲染

```jsx
import React, { Component } from 'react'

class Counter extends Component {
constructor(props) {
super(props)
// 初始化 state
this.state = {
count: 0
}
}

// 增加计数的方法
incrementCount = () => {
// 更新状态
this.setState({ count: this.state.count + 1 })
}

render() {
return (
<div>
<p>Count: {this.state.count}</p>
<button onClick={this.incrementCount}>Increase</button>
</div>
)
}
}

export default Counter
```

同时React还在类组件中提供了一套生命周期的钩子,如以下:

- 挂载阶段(Mounting):组件被创建并插入 DOM。
- 更新阶段(Updating):组件的状态或 props 发生变化时触发更新。
- 卸载阶段(Unmounting):组件从 DOM 中移除。

这给开发者提供了实现副作用功能的地方,比如:请求数据,销毁内存等。平常基础开发都会使用类组件来进行开发,上面的写法在量上面还是比较的多和麻烦。

接下来说下函数组件,hooks之前,函数组件就是单纯的ui组件,hooks引入过后函数组件就可以做到同类组件相同的事件了。hooks使用相当于在之前函数组件的基础上加入了一些状态函数的调用,常见的hooks如下:

- useState:定义一个状态的变量,返回使用和修改的变量。这个hook就是对应类型的state功能
- useEffect:入参1为函数,入参2为监听的变量数组,当监听的变量有改动时就会调用入参1的函数,具体使用可看官网。该hook就是对应了类组件中的生命周期了。
- useCallback:入参1为函数,入参2为监听的变量数组,返回一个函数提供调用, 当监听的变量有修改就会修改返回的函数,通过这样可以做到函数的缓存
- useMemo:类似useCallback,不过是缓存的值。

以上是一常用的hooks。通过这些hooks,函数组件可以做到和类型一样的事,同时代码更加简洁和清晰,因此现在基本都使用函数组件来进行开发。函数组件也更加锲合`F()=UI`,更能体现React的理念。

## React 的渲染机制

React 使用虚拟 DOM来优化真实 DOM 的更新。每次状态变化时,React 通过重新渲染组件生成新的虚拟 DOM,并与旧的虚拟 DOM 进行 Diff 比较,最终最小化真实 DOM 的更新。

深入理解:

- 虚拟 DOM:它是 React 使用的一种数据结构,表示 UI 的当前状态。通过 React.createElement 方法创建节点树。
- Diff 算法:React 使用的 Diff 算法通过最小化计算量找到需要更新的地方。掌握这些算法有助于理解为什么有些复杂 UI 操作可能导致性能问题。
- 渲染优化:使用 shouldComponentUpdate(类组件)或 React.memo(函数组件)来避免不必要的渲染。

虚拟DOM就是对真是的dom数做的一层抽象展示,通过js对象来模拟这棵树,当用户操作后页面需要改动时,会再次生成一个更新后的数,然后使用diff算法来找到需要更新的地方,最后对页面上的dom进行操作,以此来完成更新。这些都是框架内部的操作,React已经做好了优化,开发者能做的是在生成这课新的dom树的过程中进行优化,也就是具体代码的优化。

比如类组件的`shouldComponentUpdate`方法,入参为下一次的`Props``State`等数据,通过返回`True` or `False` 判断组件是否更新。在函数组件中也有优化的手段,比如

- useCallback,缓存函数
- useMemo,缓存值

除了上面的一些点,还有就是函数组件本身的优化。每一次state的变更,函数组件就会像执行函数那样重新执行该组件,组件内部的声明变量也会重新构建,上面的那些优化hook也就可以用起来了,同时子组件也会重新执行,这个时候无论子组件做了什么优化都会重新执行子组件,所有在进行代码拆分时尽可能的减少父组件的state。

## 代码分割和懒加载

对于大型应用,代码分割和懒加载是优化加载时间和提升性能的重要策略。React 提供了 React.lazy 和 Suspense,帮助你实现按需加载组件。

实现方法:

- React.lazy:将组件懒加载,避免在初始加载时加载过多的代码。
- React.Suspense:为懒加载组件提供占位符,直到组件加载完成。

0 comments on commit 358afa4

Please sign in to comment.