美文网首页我爱编程
2018-01-26组件性能优化

2018-01-26组件性能优化

作者: yzr_0802 | 来源:发表于2018-01-30 14:18 被阅读0次

    总结:
    无论是PureRender还是key值,整个React组件的优化逻辑都是针对Virtual DOM的更新优化。

    1.纯函数的三大原则

    • 给定相同的输入,他总是返回相同的输入
    • 过程没有副作用(不能改变外部状态)
    • 没有额外的状态依赖(方法内的状态只在方法的生命周期中存活)

    2.PureRender

    1.PureRender本质

    • 只对新旧props和state做了浅比较(只做了引用)比较,没有做值的比较);如果返回false,组件就不执行render方法,默认情况返回true。react-addons-pure-render-mixin插件允许我们使用PureRender。
      源码:
        function shallowEqual(obj,newObj){
            if(obj===newObj){
                  return true;
             }
            const objKeys=Object.keys(obj);
            const newObjKeys=Object.keys(newObj);
            if(objKeys.length!==newObjKeys.length){
                  return false;
            }
            //只需关注props中的每一个是否相等,无需深入判断。
            return objKeys.every(key=>{
                  return  newObj[key]===obj[key]
            });
        }
    

    2.在组件中使用:

     import React,{component} from ‘react’;
     import PureRenderMixin from ‘react-addons-pure-render-mixin’;
            
    class App extends Component{
          constructor(props){
                super(props);
                this.shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this);
          }
        render(){
                return <div calssName = {this.props.className}>foo</div>;
        }
    }
    

    3.优化PureRender
    1)不能直接为props设置对象或数组;
    需要提前将赋值成常量,不直接使用字面量。因为我们每次调用React组件其实都会重新创建组件,就算传入的数组或对象没有改变,但是他们的引用地址还是会发生变化。
    2)设置props方法并通过实践绑定在元素上
    我们不用每次都绑定事件,可以将它绑定移到构造器中
    3)设置子组件
    对于设置了子组件的React组件,再调用shouldComponentUpdate时,均返回true;如何避免子组件重复渲染,就是在他的父组件中设置

     this.shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this);
    

    3.Immutable

    由于js一般对象赋值都是引用赋值,所以一般都是可变的,这样改变一个值,原来的值也会发生变发。因此是可变的(mutable)。
    为了解决这个问题。
    -1.使用浅拷贝或深拷贝来避免被修改。
    -2. immutable数据是一旦创建,就不能在更改的数据,对Immutable进行修改,删除,添加都会返回一个新的Immutable对象。也就是Immutable原理就是持久化的数据结构,也就是使用旧数据创建新数据的时,要保证旧数据同时可用且不可变。Immutable数据使用了结构共享,即如果对象树中一个节点变化,只修改这个节点和受她影响的父节点,其他节点则进行共享。

    Immutable.js简介:

    • 1.Immutable优点
      1)降低了“可变”带来的复杂度
      2)节省内存;实现结构共享,没有被引用的对象对被垃圾回收。
      3)撤销/重做,复制/粘贴,甚至时间旅行这些功能做起来都是小菜一碟。因为每次数据都是不一样的,只要把它们存到一个数据中,想退回哪里就拿出来就可以了,不用担心会发生变化。
      4)并发安全。但是js是单线程的,所以目前没什么用。
      5)函数式编程。只要输入一直,输出必然一致。
    • 2.Immutable缺点
      容易与原生的对象混淆。
      避免该缺点
      1)使用FlowType或TypeScript静态类型检查工具
      2)约定变量命名规则,如所有Immutable对象都用$$开头
      3)使用Immutable.fromJS而不是用Immutable.Map或Immutable.List来创建对象。这样可以避免Immutable对象和原生对象间的混用。
    • 3.Immutable.is
      比较两个Immutable对象的值用的是Immutable.is(a,b);"值比较";
    import Immutable from 'immutable';
    let a=Immutable.fromJS({a:1,b:2,c:3});
    let b=Immutable.fromJS({a:1,b:2,c:3});
    
    console.log(1,a===b);//false
    console.log(2,Immutable.is(a,b));//true
    
    • 4.Immutable和cursor
      cursor提供了可以直接访问这个深层数据的引用。
    import Immutable from 'immutable';
    
    let data=Immutable.fromJS({a:{b:{c:1}}});
    let cursor=Cursor.from(data,['a','b'],newData=>{console.log(newData)});
    console.log(1,cursor.get('c'));//1
    cursor=cursor.update('c',x=>x+1);
    console.log(2,cursor.get('c'));//2
    
    • 5.Immutable与PureRender
      提供了is和===比较重写了shouldComponentUpdate;
      使用immutable data之后,仅仅改变状态了的组件及其父组件被重新渲染。
    import React,{ commponent } from 'react';
    import { is } from 'immutable';
            
    class App extends Component {
          shouldComponentUpdate(nextProps, nextState){
               const thisProps = this.props || {};
               const thisStae = this.state || {};
               if (Object.keys(thisProps).length !== Object.keys(nextProps).length ||
                        Object.keys(thisState).length !== Object.keys(nextState).length){
                        return true;
                 }
                for (const keys in nextProps){
                       // !==判断原生对象,is判断immutable对象
                        if (thisProps[key] !== nextProps[key] ||
                                !is(thisProps[key], nextProps[key]))
                            return true;
                    }
                 for (const key in nextState){
                        if ( thisStae[key] !== nextState[key])||
                            !is(thisStae[key],nextState[key])
                        return true;
                    }
             }
    }
    
    • 6.Immutable和setState
      React建议把this.state当做不可变的,因此修改钱需要做一个深拷贝。
     import React,{component} from ‘react’;   
    import {Map}from 'immutable';    
    class App extends Component{
          constructor(props){
                super(props);
                this.state={
                        data:Map({time:0})
                  }
          }
          handleAdd(){
              this.setState(({data})=>({data:data.update('time',v=>v+1)}));
             console.log(this.state.data.get('time'));//这里的time是修改前的值0;
          }
    }
    
    

    4.key

    1)如果子组件是一个数组或迭代器,那么必须有一个唯一的key prop;
    2)注意设置key值不要使用index或随机值。因为这个index不是唯一的而且还会变化。
    3)当key相同是,只渲染第一个相同key的项,且会报一个警告。

    相关文章

      网友评论

        本文标题:2018-01-26组件性能优化

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