资讯专栏INFORMATION COLUMN

react如何性能达到最大化(前传),暨react为啥非得使用immutable.js

jubincn / 3334人阅读

摘要:主要讲述我一步一步优化性能的过程。。才能将的性能发挥到极致要是各位看官用过一段时间的,而没有用那么本文非常适合你。那么多么浪费性能,好。。下一篇我讲写,,如何用

一行代码胜过千言万语。。这篇文章呢。。主要讲述我一步一步优化react性能的过程。。为啥要用immutable.js呢。毫不夸张的说。有了immutable.js(当然也有其他实现库)。。才能将react的性能发挥到极致!要是各位看官用过一段时间的react,而没有用immutable那么本文非常适合你。那么我开始吧!

1,对于react的来说,如果父组件有多个子组件

想象一下这种场景,一个父组件下面一大堆子组件。然后呢,这个父组件re-render。是不是下面的子组件都得跟着re-render。可是很多子组件里面是冤枉的啊!!很多子组件的props 和 state 然而并没有改变啊!!虽然virtual dom 的diff 算法很快。。但是性能也不是这么浪费的啊!!下面我们上代码

1.原始代码如下

以下是父组件代码。。负责输入name 和 age 然后循环显示name 和 age

   export default class  extends Component {
      constructor(props){
        super(props)
        this.state={
          name:"",
          age :"",
          persons:[]
        }
      }
      render() {
        const {name,age,persons} = this.state
        return (
          
姓名: 年龄: {persons.map((person,index)=>( ))}
) } _handleChange(event){ this.setState({[event.target.name]:event.target.value}) } _handleClick(){ const {name,age} = this.state this.setState({ name:"", age :"", persons:this.state.persons.concat([{name:name,age:age}]) }) } }

以下是子组件代码单纯的显示name和age而已

class Person  extends Component {
  componentWillReceiveProps(newProps){
    console.log(`我新的props的name是${newProps.name},age是${newProps.age}。我以前的props的name是${this.props.name},age是${this.props.age}是我要re-render了`);
  }
  render() {
    const {name,age} = this.props;

      return (
        
姓名: {name} age: {age}
) } }

运行起来长下图这个样

好那么问题来了。。我们看一下控制台

天哪,,这么多次re-reder..细细观看。。不难发现。要re-render这么多次。。父组件一re-render,子组件就跟着re-render啊。。那么多么浪费性能,好。。PureRenderMixin出场

2,PureRenderMixin

因为咱用的是es2015的 Component,所以已经不支持mixin了。。不过没关系,可以用
HOCs,这个比mixin还更受推崇呢。。我有空回用代码来展示他俩的异同,鉴于不是本文重点,,大家可以看这两篇文章了解下React Mixin 的前世今生 和Mixins Are Dead. Long Live Composition
所以在这里我们用Pure render decorator代替PureRenderMixin,那么代码如下

import pureRender from "pure-render-decorator"
...

@pureRender
class Person  extends Component {
  render() {
    console.log("我re-render了");
    const {name,age} = this.props;

      return (
        
姓名: {name} age: {age}
) } }

加个这东西就完事了??看上去咋这么不令人信服啊。。不管怎样。。试试吧

果然可以做到pure render。。在必须render 的时候才render
好我们看看它的神奇之处

@pureRender

是es7的Decorators语法。上面这么写就和下面这么写一样

class PersonOrigin  extends Component {
  render() {
    console.log("我re-render了");
    const {name,age} = this.props;

      return (
        
姓名: {name} age: {age}
) } } const Person = pureRender(PersonOrigin)

pureRender其实就是一个函数,接受一个Component。把这个Component搞一搞,返回一个Component
看他pureRender的源代码就一目了然

function shouldComponentUpdate(nextProps, nextState) {
  return shallowCompare(this, nextProps, nextState);
}

function pureRende(component) {
  component.prototype.shouldComponentUpdate = shouldComponentUpdate;
}
module.exports = pureRender;

pureRender很简单,就是把传进来的component的shouldComponentUpdate给重写掉了,原来的shouldComponentUpdate,无论怎样都是return ture,现在不了,我要用shallowCompare比一比,shallowCompare代码及其简单,如下

function shallowCompare(instance, nextProps, nextState) {
  return !shallowEqual(instance.props, nextProps) || !shallowEqual(instance.state, nextState);
}  

一目了然。分别拿现在props&state和要传进来的props&state,用shallowEqual比一比,要是props&state都一样的话,就return false,是不是感觉很完美?不。。这才刚刚开始,问题就出在shallowEqual上了

3,shallowEqual的问题 shallowEqual引起的bug

很多时候,父组件向子组件传props的时候,可能会传一个复杂类型,比如我们改下。

  render() {
    const {name,age,persons} = this.state
    return (
      
...省略..... {persons.map((person,index)=>( ))}
) }

person是一个复杂类型。。这就埋下了隐患,,在演示隐患前,我们先说说shallowEqual,是个什么东西,shallowEqual其实只比较props的第一层子属性是不是相同,就像上述代码,props 是如下

{
    detail:{
       name:"123",
       age:"123"}
}

他只会比较props.detail ===nextProps.detail
那么问题来了,上代码
如果我想修改detail的时候考虑两种情况

情况一,我修改detail的内容,而不改detail的引用

这样就会引起一个bug,比如我修改detail.name,因为detail的引用没有改,所以
props.detail ===nextProps.detail 还是为true。。
所以我们为了安全起见必须修改detail的引用,(redux的reducer就是这么做的)

情况二,我修改detail的引用

这种虽然没有bug,但是容易误杀,比如如果我新旧两个detail的内容是一样的,岂不是还要,render。。所以还是不完美,,你可能会说用 深比较就好了,,但是 深比较及其消耗性能,要用递归保证每个子元素一样,

这只是说没有用immutable引起各种?。。下一篇我讲写,,如何用immutable.js..

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/78476.html

相关文章

  • vue2.0源码分析之理解响应式架构

    摘要:分享前啰嗦我之前介绍过如何实现和。我们采用用最精简的代码,还原响应式架构实现以前写的那篇源码分析之如何实现和可以作为本次分享的参考。到现在为止,我们再看那张图是不是就清楚很多了总结我非常喜欢,以上代码为了好展示,都采用最简单的方式呈现。 分享前啰嗦 我之前介绍过vue1.0如何实现observer和watcher。本想继续写下去,可是vue2.0横空出世..所以 直接看vue2.0吧...

    chenatu 评论0 收藏0
  • react 实现pure render的时候,bind(this)隐患

    摘要:即使用也不好使。。。原来啊,父组件每次,都会执行这样的引用每次都会改。。所以前后两次其实是不一样的。。那怎么办把去掉不行还必须得用真正的答案是让父组件每次不执行,直接提前在执行好,修改之后改成这样参考。。 pure render 我就不多说了,附上我另一片文章链接 react如何性能达到最大化(前传)不论你用不用immutable,只要你想达到pure render,下面值得你注意!!...

    LiveVideoStack 评论0 收藏0
  • React性能优化(一)当 PureComponent 遇上 ImmutableJS

    摘要:四是在年出的持久性数据结构的库,持久性指的是数据一旦创建,就不能再被更改,任何修改或添加删除操作都会返回一个新的对象。避免大量使用操作,这样会浪费性能。尽量将设计成扁平状的。 一、痛点 在我们的印象中,React 好像就意味着组件化、高性能,我们永远只需要关心数据整体,两次数据之间的 UI 如何变化,则完全交给 React Virtual Dom 的 Diff 算法 去做。以至于我们很...

    plus2047 评论0 收藏0
  • react进阶漫谈

    摘要:父组件向子组件之间非常常见,通过机制传递即可。我们应该听说过高阶函数,这种函数接受函数作为输入,或者是输出一个函数,比如以及等函数。在传递数据的时候,我们可以用进一步提高性能。 本文主要谈自己在react学习的过程中总结出来的一些经验和资源,内容逻辑参考了深入react技术栈一书以及网上的诸多资源,但也并非完全照抄,代码基本都是自己实践,主要为平时个人学习做一个总结和参考。 本文的关键...

    neuSnail 评论0 收藏0
  • react进阶漫谈

    摘要:父组件向子组件之间非常常见,通过机制传递即可。我们应该听说过高阶函数,这种函数接受函数作为输入,或者是输出一个函数,比如以及等函数。在传递数据的时候,我们可以用进一步提高性能。 本文主要谈自己在react学习的过程中总结出来的一些经验和资源,内容逻辑参考了深入react技术栈一书以及网上的诸多资源,但也并非完全照抄,代码基本都是自己实践,主要为平时个人学习做一个总结和参考。 本文的关键...

    wyk1184 评论0 收藏0

发表评论

0条评论

jubincn

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<