美文网首页
react 的一些点滴

react 的一些点滴

作者: Lyan_2ab3 | 来源:发表于2020-02-07 12:32 被阅读0次

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.PureComponentReact.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

相关文章

网友评论

      本文标题:react 的一些点滴

      本文链接:https://www.haomeiwen.com/subject/sismthtx.html