这是我参与「第五届青训营 」伴学笔记创作活动的第7天。
一、本堂课重点内容
- useState
- 副作用,useEffect
- React的实现
二、详细知识点介绍
hooks
副作用:有的组件状态变化后会对组件外部的状态造成影响,比如发起网络请求,或在localStorage中保存了字段。
副作用是相对于主作用来说的,一个函数除了主作用,其他的作用就是副作用。对于 React 组件来说,主作用就是根据数据(state/props)渲染 UI,除此之外都是副作用(比如,手动修改 DOM)
常见的副作用
- 数据请求 ajax发送
- 手动修改dom
- localstorage操作
useEffect执行的时机:
- 不添加第二个参数组件首次渲染执行一次,以及不管是哪个状态更改引起组件更新时都会重新执行
- 第二个参数为空数组[],组件只在首次渲染时执行一次
- 第二个参数为数组,数组内有某些状态[count],则副作用函数在组件首次渲染时执行,在依赖项发生变化时重新执行
不要在循环或条件语句中使用useEffect!!!
React的实现
React的代码无法直接在浏览器运行
- JSX不符合JS标准语法——转译,转成浏览器可以执行的JS代码
- 返回的JSX发生改变时,如何更新DOM
- 直接重新渲染,开销太大
- 用一个diff表示原来DOM与更新后的差异,但diff的算法开销不能太大
- React提出了虚拟DOM (Virtual DOM)
- Virtual DOM是一种用于和真实DOM同步,而在JS内存中维护的一个对象,它具有和DOM类似的树状结构,并和DOM可以建立一一对应的关系。
- 真实的DOM不是JS对象,而是浏览器内部的对象,JS只能通过浏览器的DOM接口修改DOM,而无法直接拿到DOM
- React文档:它赋予了React声明式的API :您告诉React希望让UI是什么状态, React就确保DOM匹配该状态。这使您可以从属性操作、事件处理和手动DOM更新这些在构建应用程序时必要的操作中解放出来。
- 补充:
- 指令式编程:手动告诉程序,一步一步怎么做,C/C++
- 声明式编程:直接声明,无需指定更底层的事情,当前所有的前端框架都是声明式编程,但浏览器要提供底层接口,所以没实现声明式接口
- 响应式编程:是声明式编程的一个类别,某个状态改变可自动更改别的状态
- State/Props更新时,如何重新触发render
- 当父组件的状态变化时,会递归地导致子组件状态变化,这些组件的render要重新执行一遍
- 通过局部最优算法,React提出了启发式的Heuristic O(n)算法,并不是全局最优,但是换取了时间
- 2棵DOM树,从根节点开始递归地比较:
- 遇到不同类型的元素,如div和span,则直接替换子树
- 遇到同类型的DOM元素,而属性发生变化,则更新元素
- 遇到同类型的组件元素,则递归地继续比较,React在这一步性能受影响,因为只要父组件状态变化,会递归地导致子组件执行render
三、实践实习例子
useState
import React,{useState} from 'react';
const [count, setCount] = useState(0);
//count是状态名,setCount是修改状态的函数,useState的参数是状态初始值
setCount(count + 1);//通过调用setCount修改状态值
useEffect
useEffect(()=>{
console.log('副作用执行了')
})//组件首次渲染执行一次,以及不管是哪个状态更改引起组件更新时都会重新执行
useEffect(()=>{
console.log('副作用执行了')
},[])//组件只在首次渲染时执行一次
useEffect(()=>{
console.log('副作用执行了')
},[count])//副作用函数在首次渲染时执行,在依赖项发生变化时重新执行
四、课后个人总结
本节课讲了React的hooks写法,介绍了通过useState设置和改变组件状态,通过useEffect实现组件的副作用,并进行了实践练习。本节课还讲了React的实现,即如何解决JSX语法不符合JS语法,DOM树如何更新和render函数执行时机的问题,介绍了React中DOM树的比对方式,并分析了影响React性能的因素。