美文网首页我爱编程
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