响应式系统与React | 青训营笔记

71 阅读4分钟

这是我参与「第五届青训营」伴学笔记创作活动的第 6 天

| 本堂课重点内容

本堂课重点讲述了React的发展和设计思路。

| React的发展与应用

React 起源于 Facebook 的内部项目,用来架设Instagram 的网站。由于使用效果极佳,就被决定在2013年5月开源了。

React的常见应用场景

  • 前端应用开发:Facebook、Instagram、Netfix网页版等
  • 移动原生应用开发:Instagram、Discord、Oculus等
  • 桌面应用开发:结合Electron

| React的设计思路

  1. 定位编程痛点:UI更新

  2. 响应式与转换式系统

  3. 响应式编程:事件 → 执行既定的回调 → 状态变更 →UI更新

  4. 组件化

    • 组件是组件的组合/原子组件
    • 组件内拥有状态,外部不可见
    • 父组件可将状态传入组件内部
  5. 状态归属

    状态归属于两个节点向上寻找到的最近的祖宗节点

    思考:

    1. React是单向数据流, 还是双向数据流?
    • 单向。
    1. 如何解决状态不合理上升的问题?
    2. 组件的状态改变后,如何更新DOM ?
  6. 生命周期

    React组件的生命周期可分成三个状态:

    • Mounting(挂载):已插入真实 DOM
    • Updating(更新):正在被重新渲染
    • Unmounting(卸载):已移出真实 DOM

| React Hooks的写法与React实现

  • 指令式编程
  • 声明式编程
  • 响应式编程

注意:不要在循环,条件或嵌套函数中调用Hook

useState()


const [size, setSize] = useState({ width: 0, height: 0})
const handleContainerResize = ({ width, height }) => {
  setSize({width, height})
}

const [name, setName] = useState("zhangsan");
const [value, setValue] = useState(0)
const change = (event) => {
    setName(event.target.value)
  }

  return (
    <div>
      <div>{value}</div>
      <button onClick={() => setValue(value + 1)} >加一</button>
      <input onChange={change} value={name}/>
    <div/>
  )

useEffect()

函数的副作用就是函数除了返回值外对外界环境造成的其它影响,大致可以分为两类:

  • 调用浏览器的API

  • 发起获取服务器数据的请求

  • useEffect与依赖项:

    • useEffect(() => {...}) 每次组件渲染都执行
    • useEffect(() => { return () => {...} }, []) 组件第一次渲染执行,组件移除时触发clean函数
    • useEffect(() => { return () => {...} }, [dep])dep改变才会执行,组件重新渲染前触发clean函数
  • useEffect与useLayoutEffect

    • useEffect 的函数会在组件渲染到屏幕之后执行
    • useLayoutEffect则是在DOM结构更新后、渲染前执行,相当于有一个防抖效果

useRef()

useRef是用来在组件不同渲染之间共用一些数据的,作用与类组件中this赋值相似。

  • 赋值:const life = useRef(null)
  • 修改:life.current  = "Life is worth lliving."

useCallBack()

const memoizedCallback = useCallback(callback, dependencies)
  • 参数1是一个回调函数,是需要被记住的函数
  • 参数2是参数1中函数的依赖项,只有dependencies数组里面的元素的值发生变化时useCallback才会返回新定义的函数,否则useCallback都会返回之前定义的函数

useMemo()

useMemo与useCallback的作用类似,区别是useMemo允许记住任何类型的变量(函数、对象...)

useContext()

父子组件传值、全局共享数据

  1. 导入createContext ,使用createContext 创建Context对象
  2. 在顶层组件通过Provider 提供数据
  3. 在底层组件通过useContext函数获取数据

useReducer()

useReducer允许我们在函数组件里面像使用redux一样通过reducer和action来管理我们组件状态的变换

const [state, dispatch] = useReducer(reducer, initialArg, init)
  • reducer - 状态转换函数,(currentState, action) => newState,接收当前的state和当前dispatch的action为参数,然后返回下一个state。
  • initialArg - 如果调用者没有提供第三个init参数,这个参数代表的是这个reducer的初始状态;如果init参数被指定,initialArg会被作为参数传进init函数来生成初始状态。
  • init - 生成初始状态函数,(initialArg) => initialState,接收useReducer的第二个参数initialArg作为参数,并生成一个初始状态initialState。

diff算法规则:

  • 不同类型元素 -- 替换
  • 相同类型的DOM元素 -- 更新
  • 相同类型的组件元素 -- 递归

| React状态管理库与应用级框架科普

React状态管理库:(核心)将状态抽离到UI外部进行统一管理

  • redux
  • xstate
  • mobx
  • recoil
  • 字节开发 - modern.js/reduck

状态机:当前状态,收到外部事件,迁移到下一个状态

应用级框架

  • next.js:稳定,开发体验好,支持Unbundled Dev,SWC等,其同样有Serverless一键部署平台帮助开发者快速完成部署。
  • modern.js:字节跳动Web Infra 团队研发的全栈开发框架,内置了很多开箱即用的能力与最佳实践,可以减少很多调研选择工具的时间。
  • Blitz:无API思想的全栈开发框架,开发过程中无需写API调用与CRUD逻辑,适合前后端紧密结合的小团队项目。

个人总结

本次课是对React的一个基础引入,不仅介绍了React的发展、应用场景,还介绍了一些React的钩子函数、状态管理库等,在学习完基础的React之后,我们可以更深一步学习一些基于React的应用级框架。