React中的setState执行机制是什么呢?
类组件和函数式组件有何不同?
1、函数组件只是返回一个DOM 结构的函数,其实是无状态的思想;
2、函数组件,无法使用state,只是接受props,无法使用组件的生命周期,只是展示渲染无关其他;
3、函数组件更容易理解。当你看到一个函数组件时,你就知道它的功能只是接收属性,渲染页面,它不执行与UI无关的逻辑处理,它只是一个纯函数。而不用在意它返回的DOM结构有多复杂
4、而且函数组件的性能比类组件的性能要高,因为类组件使用的时候要实例化,而函数组件直接执行函数取返回结果即可
组件类的缺点:
- 大型组件很难拆分和重构,也很难测试;
- 业务逻辑分散在各个组件的方法中,导致重复和关联的逻辑;
- 组件类引入了复杂的编程模式
函数组件:
- 组件最早就支持函数,但是只能是一个纯函数,不能包含状态,也不支持生命周期方法
React Hooks 的设计目的,就是加强版函数组件,完全不使用"类",就能写出一个全功能的组件。
- 如果需要外部功能和副作用,就用钩子把外部代码"钩"进来。React Hooks 就是那些钩子。
- 在多数情况下,组件很难拆分成更小的颗粒,复用更加困难,而Hook 将组件中相互关联的部分拆分成更小的函数
- Hook 使你在非 class 的情况下可以使用更多的 React 特性
react hooks 最长用的钩子:
-
useState() :
用于为函数组件引入状态(state) -
useContext():
如果需要在组件之间共享状态,可以使用useContext() -
useReducer():
-
useEffect():
用来引入具有副作用的操作,最常见的就是向服务器请求数据。以前,放在componentDidMount里面的代码,现在可以放在useEffect();
第一个参数是一个函数,异步操作的代码放在里面;
第二个参数是一个数组,用于给出 Effect 的依赖项,只要这个数组发生变化,useEffect()就会执行。
第二个参数可以省略,这时每次组件渲染时。
react 中refs 的作用?
1、Refs 是 React 提供给我们的安全访问 DOM 元素或者某个组件实例的句柄
2、
setState 为什么是异步的?是什么时候是异步的?
setState 本身的执行过程是同步的,只是因为react 合成事件与钩子函数中执行顺序在更新之前,所以不能直接拿到更新后的数据,形成了所谓的异步;
1、可以同步,在原生事件和setTimeout 中同步
2、在合成事件与钩子函数中会对多次setState进行更新优化,只执行最后一次;
3、在原生事件与setTimeout内不会进行批量更新优化
//测试setState同步与异步
//关于react的批量更新优化
//在react的合成事件函数与钩子函数中会进行批量更新优化
//多次调用setState只会调用最后一次
class App extends React.Component{
constructor(props){
super(props);
this.state={
num:1
}
}
componentDidMount(){
this.clickFunc();
}
//num增加
//合成事件、钩子函数内进行了批量更新优化
addNum(e){
console.log('react合成事件函数');
this.setState({num:this.state.num+1});
this.setState({num:this.state.num+1});
this.setState({num:this.state.num+1});
this.setState({num:this.state.num+1});
console.log(this.state.num);
}
//原生点击事件的处理函数
//原生事件与setTimeout中不会进行批量更新
clickFunc(){
document.querySelector('#btn').addEventListener('click',()=>{
console.log('原生事件处理函数开始');
this.setState({num:this.state.num+1});
console.log(this.state.num);
this.setState({num:this.state.num+1});
console.log(this.state.num);
this.setState({num:this.state.num+1});
console.log(this.state.num);
this.setState({num:this.state.num+1});
console.log(this.state.num);
console.log('原生事件处理完成');
})
}
render(){
return(
<div>
<h1>{this.state.num}</h1>
{/* react的合成事件 */}
<button onClick={(e)=>{this.addNum(e)}}>React合成事件的按钮</button>
{/* 原生DOM事件 */}
<button id='btn'>绑定原生DOM事件的按钮</button>
</div>
)
}
}
ReactDom.render(<App/>,document.querySelector('#app'));
————————————————
setState 批量更新是按照先进先出的原则,顺序更新;
无论你在多少个组件中调用多少个 setState,它们都会在最后一次 setState 后,全部放在同一个队列里,然后执行一个统一的更新,而不会说是 在父组件 re-render 一次,在子组件又 re-render 一次
export default class Child extends Component {
constructor(props){
super(props)
this.state={
b:false,
c:false,
}
}
componentDidMount() {
this.setState({b:true})
console.log(this.state,'first')
this.setState({c:true})
console.log(this.state,'second')
}
render() {
console.log(this.state,'render')
return <div>
</div>
}
}
结果:
{b: false, c: false} "render"
{b: false, c: false} "first"
{b: false, c: false} "second"
{b: true, c: true} "render"
但是在 Ajax、setTimeout 等异步方法中,每 setState 一次,就会 re-render 一次
export default class Child extends Component {
constructor(props){
super(props)
this.state={
b:false,
c:false,
}
}
componentDidMount() {
let aPromise = new Promise((resolve)=> {
resolve(100)
})
aPromise.then((value)=> {
this.setState({b:true}) //re-render
console.log(this.state,'first')
this.setState({c:true}) //re-render
console.log(this.state,'second')
});
}
render() {
console.log(this.state,'render')
return <div>
</div>
}
}
{b: false, c: false} "render"
{b: true, c: false} "render"
{b: true, c: false} "first"
{b: true, c: true} "render"
{b: true, c: true} "second"
- 在异步调用的方法中(promise.then()、setTimeout)通过 unstable_batchedUpdates() 强制将 多个setState 置在同一更新队列中,一起更新
- 在异步调用的方法里(setTimeout、promise.then())使用 unstable_batchedUpdates() 更新的队列排在 React 默认队列的后面
React.setState 的内部更新队列, 本质上就是放在 unstable_batchedUpdates() 里的。但如果在 unstable_batchedUpdates() 中嵌套 unstable_batchedUpdates() 的话,React 是不会 re-render 两次的,React 会找到 最外层的 unstable_batchedUpdates ,然后将里面所有的 setState 放到同一个队列中,render 一次
注意:setState中的对象合并都是->浅合并
React.PureComponent:
React.PureComponent
与React.Component
很相似。两者的区别在于React.Component
并未实现shouldComponentUpdate()
,而React.PureComponent
中以浅层对比 prop 和 state 的方式来实现了该函数。
React.PureComponent 中的 shouldComponentUpdate() 仅作对象的浅层比较。 如果对象中包含复杂的数据结构,则有可能因为无法检查深层的差别,产生错误的比对结果
。 所以在props 和 state 比较简单的时候才会使用 React.PureComponent。
React.memo
高阶组件,与React.PureComponent 非常相似,但是只使用于函数组件,不适用于class 组件
参考链接:https://blog.csdn.net/qq_39989929/article/details/94041143
网友评论