这是我参与「第四届青训营 」笔记创作活动的的第5天。本篇笔记是对 响应式系统与React 的课程总结,并结合了自己搜集了解的内容,进行了一定的梳理。有意见和建议也欢迎在评论区交流讨论呀~
知识点
- React 的历史与设计
- React 与 hooks 写法
- React 实现
- 状态管理库与应用级框架
React 介绍
应用场景:
- 前端网页应用开发,如 Facebook,Instagram 网页
- 移动原生应用,如 Instagram APP
- 桌面应用开发,结合 Electron
- 3D 开发,React-three-fiber(WebGL)
React 起源
- 2010 年 Facebook 在 php 生态中引入 XHP 框架,首次引入组合式组件的思想
- 2011 年 FaxJS 框架 (github.com) 发布
- 2013 年 React 开源
[JSConfUS 2013] Tom Occhino and Jordan Walke: JS Apps at Facebook(React诞生的历史与简介)_哔哩哔哩_bilibili
FaxJS 特性:
- 客户端服务端渲染——无缝切换
- 响应式 —— 状态变更时视图 UI 自动更新,无需绑定
- 高性能 —— 使用字符串拼接方式高速渲染,缩小代码体积
- 结构化 —— 高级组件封装,函数式声明、声明式视图
设计思路
UI 编程痛点:
- 状态更新,UI 不会自动更新,需要调用 DOM 接口 API
- 无封装隔离,代码层面没有组件化
- UI 与数据之间的依赖关系需要手动维护,容易遇到回调地狱
过程式与响应式:
需求:
- 状态更新,UI 自动更新
- 前端代码组件化,可复用,可封装
- 状态之间互相依赖关系,只需声明
设计实现:
- 组件是组件的组合/原子组件
- 组件有自己的状态,外部不可见
- 父组件可以将状态传入组件内部
思考问题:
- React 是单向数据流,还是双向数据流?单向数据流,仅能父向子组件传值
- 如何解决状态不合理上升
- 组件状态改变后,如何更新 DOM
组件设计:
- 组件声明了状态和 UI 映射
- 组件有 props 和 state 两种状态(父组件状态和当前组件自己的状态)
- 组件可以有其他组件拼装而成
生命周期:
从组件渲染阶段开始,组件的创建、状态更新都会触发渲染,并将渲染结果更新到虚拟 DOM 上。commit 阶段,React 更新改变的结果到 DOM 上。
React hooks
hooks 写法
import React, { useState } from 'react';
function Example() {
// 声明一个新的叫做 “count” 的 state 变量 const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
副作用
副作用(side-effect)是指让一个函数变得不再纯净(pure)的东西。
副作用是必须的,只有完全孤立的系统才没有副作用。
使用 Effect hook 实现副作用。默认情况下,React 会在每次渲染后调用副作用函数 —— 包括 第一次渲染的时候
React 的实现
JSX 到 JS 的转换
使用转译实现 Markup 语言的转换(HTML 容易被转换)
使用虚拟DOM 实现 DOM 的更新
Virtual DOM:用于和真实 DOM 同步,而在 JS 内存中维护的一个对象,这个对象具有和 DOM 类似的树形结构,并可以和 DOM 建立一一对应的关系。赋予了 React 声明式的 API(向 React 表达了希望让 UI 是什么状态,React 会自动确保 DOM 匹配该状态)
DOM 操作耗时长,
使用 diff 算法检查 DOM 修改内容
diff 的实现
完美最小 Diff 算法,需要 O(n^3) 的复杂度
牺牲理论最小 Diff,换取时间得到 O(n) 算法:Heuristic O(n)
- 不同类型的元素 —— 替换
- 同类型的 DOM 元素 —— 更新
- 同类型组件元素 —— 递归
导致性能问题:当父组件改变时子组件会被递归,导致重新加载
状态管理库
核心思想:将状态抽离到 UI 外部进行统一管理
弊端:组件难复用、数据共享无法保障安全性
状态机:当前状态,收到外部事件,迁移到下一个状态
- redux
应用级框架
- next.js
- modern.js
- blitz
课后作业
- React 组件的render函数,在什么时候重新执行
由 React 组件生命周期可知,在组件挂载、使用 New props、setState、forceUpdate 更新时。但是,
shouldComponentUpdate()会阻止在 state 和 props 更新后调用 render 函数
- React 函数式编程和 Vue 基于模板语法,各自的优点与缺点
Vue 的整体思想是使用经典结构、表现、行为的形式,易于学习使用,但不够灵活有一定限制。
React 的整体思想是使用函数式编程,组件使用 jsx 语法,将 HTML 和 CSS 融入 JS,更加灵活,拥有更大的控制权但学习成本高。
- React 推荐使用组合来进行组件的复用,而不是继承,背后有怎样的考虑?
本质上解决的是组件之间传值的问题。但是它对于传值以及一些内部操控的逻辑封装得更严密。
场景:希望减少上下级组件之间props的传递,简单来说就是不用传做显式地传值,来达到组件之间相互通信的目的