美文网首页
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