babel
1 react 用的是jsx模版,最终它会返回一个jsx,它实际上会经过babel编译成react.createElement的形式
React.createElement(
type,
[props],
[...children]
)
举个例子
<div>
<Component />
<div>hello,world</div>
let us learn React!
</div>
经过babel编译成
React.createElement("div", null,
React.createElement(Component, null),
React.createElement("div", null, "hello,world"),
"let us learn React!"
)
在调和阶段,react element对象的每个子节点都会形成每个与之对应的fiber对象,fiber对象里面含有sibling、return、child信息,它可以将每个子节点联系起来。
fiber 对应关系
- child: 一个由父级 fiber 指向子级 fiber 的指针。
- return:一个子级 fiber 指向父级 fiber 的指针。
- sibling: 一个 fiber 指向下一个兄弟 fiber 的指针。
组件
组价的本质就是类和函数。
在react中有两种组件,类组件和函数组件。对于类组件来说,底层只需要实例化一次,实例中保存了组件的 state 等状态。对于每一次更新只需要调用 render 方法以及对应的生命周期就可以了。但是在函数组件中,每一次更新都是一次新的函数执行,一次函数组件的更新,里面的变量会重新声明。 这是他们的本质区别。
组件通信方式
- props和callback方式
- ref方式
- redux状态管理方式
- context上下文方式
- event bus 事件总线方式(不提倡)
state
state是异步还是同步的?
类组件中,UI的变化是源于state的变化,setState是更新组件,渲染视图的主要方式
setState(obj,callback)
- 第一个参数:当 obj 为一个对象,则为即将合并的 state ;如果 obj 是一个函数,那么当前组件的 state 和 props 将作为参数,返回值用于合并新的 state。
- 第二个参数 callback :callback 为一个函数,函数执行上下文中可以获取当前 setState 更新后的最新 state 的值,可以作为依赖 state 变化的副作用函数,可以用来做一些基于 DOM 的操作。
/* 第一个参数为function类型 */
this.setState((state,props)=>{
return { number:1 }
})
/* 第一个参数为object类型 */
this.setState({ number:1 },()=>{
console.log(this.state.number) //获取最新的number
})
在调用setState时,react 底层做了什么?
- 首先会产生当前当前更新的优先级
- 然后react 会从fiber Root 根部fiber向下调和子节点,调和阶段将对比发生更新的地方,expirationTime,找到发生更新的组件,合并state,然后调用render,得到新的UI视图,完成render阶段。
- 接下来commit阶段,此时替换真实dom,完成此次更新流程
- 还是commit阶段,会执行setState的callback回调,到此为止完成了一次 setState 全过程。
render 阶段 render 函数执行 -> commit 阶段真实 DOM 替换 -> setState 回调函数执行 callback 。
在函数组件中,我们是通过usestate 去改变state的
const [state,dispatch] = useState(initState);
- state 为视图提供数据源
- dispatch 改变state的函数,dispatch 的参数值有两种情况,一种是函数,一种是非函数。
- setValue(1)
- setValue(state=>state+1),- 是上一次返回最新的 state,返回值作为新的 state。
- initState 有两种情况,第一种是非函数,作为state初始化的值,第二种是函数,函数的返回值作为state的初始值
类组件setState和函数组件的useState有什么异同?
相同:更新视图底层都调用了scheduleUpdateOnFiber方法,而且事件驱动情况下都有批量更新规则 不同: setState 有专门的callback 可以获取到最新的state值,函数组件中没有,只能通过副作用函数useEffect来监听state的变化;setState偏向于和旧的state进行合并,useState的偏向于重新赋值。