React Native之组件Component与PureComponent

简介:

众所周知,React Native的页面元素是由一个一个的组件所构成的,这些组件包括系统已经提供的组件,如View、TextInput等,还有一些第三方库提供的组件,以及自定义的组件。通常在封装组件的时候都会继承Component,不过在React 15.3版本中系统提供了PureComponent,下面就来看一下这两个组件的区别。

首先声明,PureComponent是Component的一个优化组件,在React中的渲染性能有了大的提升,可以减少不必要的 render操作的次数,从而提高性能。PureComponent 与Component 的生命周期几乎完全相同,但 PureComponent 通过prop和state的浅对比可以有效的减少shouldComponentUpate()被调用的次数。

PureComponent VS Component 原理

当组件更新时,如果组件的props和state都没发生改变,render方法就不会触发,省去 Virtual DOM 的生成和比对过程,达到提升性能的目的。原理就是 React会自动帮我们做了一层浅比较,涉及的函数如下:

if (this._compositeType === CompositeTypes.PureClass) {
shouldUpdate = !shallowEqual(prevProps, nextProps)
|| !shallowEqual(inst.state, nextState);
}

PureComponent 的shouldComponentUpdate() 只会对对象进行浅对比,如果对象包含复杂的数据结构,它可能会因深层的数据不一致而产生错误的否定判断。所以,在实际使用的时候,当你期望只拥有简单的props和state时,才去继承PureComponent ,或者在你知道深层的数据结构已经发生改变时使用forceUpate() 。

Component

首先要看Component的生命周期示意图。
这里写图片描述
下面就Component的生命周期

生命周期

getDefaultProps

执行过一次后,被创建的类会有缓存,映射的值会存在this.props,前提是这个prop不是父组件指定的。这个方法在对象被创建之前执行,因此不能在方法内调用this.props ,另外,注意任何getDefaultProps()返回的对象在实例中共享,而不是复制。

getInitialState

控件加载之前执行,返回值会被用于state的初始化值。

componentWillMount

执行一次,在初始化render之前执行,如果在这个方法内调用setState,render()知道state发生变化,并且只执行一次。

render

调用render()方法时,首先检查this.props和this.state返回一个子元素,子元素可以是DOM组件或者其他自定义复合控件的虚拟实现 。

如果不想渲染可以返回null或者false,这种场景下,React渲染一个<noscript>标签,当返回null或者false时,ReactDOM.findDOMNode(this)返回null 。render()方法是很纯净的,这就意味着不要在这个方法里初始化组件的state,每次执行时返回相同的值,不会读写DOM或者与服务器交互,如果必须需要与服务器进行交互,可以在componentDidMount()方法中实现或者其他生命周期的方法中实现。

componentDidMount

在初始化render之后执行,且只执行一次,在这个方法内,可以访问任何组件,componentDidMount()方法中的子组件需要在父组件之前执行。

shouldComponentUpdate

这个方法在初始化render()时不会执行,当props或者state发生变化时执行,并且是在render之前执行,当新的props或者state不需要更新组件时,返回false。

shouldComponentUpdate: function(nextProps, nextState) {
  return nextProps.id !== this.props.id;
}

shouldComponentUpdate()返回false时,render()方法将不会执行,componentWillUpdate()componentDidUpdate()也不会被调用。

默认情况下,shouldComponentUpdate方法返回true,防止state快速变化时的问题,但是如果state不变,props只读,可以直接覆盖shouldComponentUpdate用于比较props和state的变化,决定UI是否更新,当组件比较多时,使用这个方法能有效提高应用性能。

componentWillUpdate

当props和state发生变化时执行,执行该函数,并且在render方法之前执行,紧接着这个函数就会调用render()来更新界面。

componentDidUpdate

组件更新结束之后执行,在初始化render时不执行。

void componentDidUpdate(
  object prevProps, object prevState
)

componentWillReceiveProps

当props发生变化时执行,初始化render时不执行,在这个回调函数里面,你可以根据属性的变化,通过调用this.setState()来更新你的组件状态,旧的属性还是可以通过this.props来获取,这里调用更新状态是安全的,并不会触发额外的render调用。

componentWillReceiveProps: function(nextProps) {
  this.setState({
    likesIncreasing: nextProps.likeCount > this.props.likeCount
  });
}

componentWillUnmount

当组件要被从界面上移除的时候,就会调用componentWillUnmount(),在这个函数中,可以做一些组件相关的清理工作,例如取消计时器、网络请求等。

PureComponent

上面为大家讲了Component的生命周期,仔细阅读可以发现,在React 的Component的生命周期中,有一个shouldComponentUpdate方法,该方法默认返回值是true。Component的shouldComponentUpdate函数源码如下:

shouldComponentUpdate(nextProps, nextState) {
  return true;
}

也就是说,不管有没有改变组件的props或者state属性,都需要调用shouldComponentUpdate()来重绘界面,这极大的降低了React的渲染效率。因此,从React在15.3版本中发布了一个优化的PureComponent组件来优化React的渲染效率。而PureComponent的shouldComponentUpdate是这样的。

if (this._compositeType === CompositeTypes.PureClass) {
  shouldUpdate = !shallowEqual(prevProps, nextProps) || ! shallowEqual(inst.state, nextState);
}

PureComponent使用浅比较判断组件是否需要重绘,因此,下面对数据的修改并不会导致重绘:

options.push(new Option())
options.splice(0, 1)
options[i].name = "Hello"

这些例子都是在原对象上进行修改,由于浅比较是比较指针的异同,所以会认为不需要进行重绘。
为了避免出现这些问题,推荐使用immutable.js。immutable.js会在每次对原对象进行添加,删除,修改使返回新的对象实例,任何对数据的修改都会导致数据指针的变化。

实例

下面,我们通过一个实例来比较下PureComponent和Component在页面渲染上面的效率。

import React, { PureComponent,Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  Button
} from 'react-native';

export default class test extends PureComponent {
  constructor(props){
    super(props);
    this.state = {
       number : 1,
       numbers: [],
    };
  }

  render() {
    return (
      <View style={styles.container}>
        <Button title={'number + 1'} onPress={this.numberAdd.bind(this)} />
        <Text>number value: {this.state.number}</Text>
        <Button title={'numbers + 1'} onPress={this.numbersAdd.bind(this)} />
        <Text>numbers length: {this.state.numbers.length}</Text>
      </View>
    );
  }

  numberAdd(){
      this.setState({number: ++this.state.number });
  }


  numbersAdd(){
    let numbers = this.state.numbers;
    numbers.push(1);
    this.setState({numbers: numbers});
    console.log(this.state.numbers);
  }


}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
  instructions: {
    textAlign: 'center',
    color: '#333333',
    marginBottom: 5,
  },
});

AppRegistry.registerComponent('test', () => test);

如何让PureComponent重绘

当然,有时候如果继承PureComponent后需要在变化的时候重绘界面,我们要怎么做?

  • 重写shouldUpdateComponent方法;
  • props或者state增减参数;

关于Component与PureComponent的内容就为大家介绍到这里,一句话:PureComponent是Component的一个优化组件,通过减少不必要的 render操作的次数,从而提高界面的渲染性能。

目录
相关文章
|
1月前
|
前端开发
react-router中的render、children、component
react-router中的render、children、component
66 1
|
1月前
|
开发框架 Dart 前端开发
【Flutter前端技术开发专栏】Flutter与React Native的对比与选择
【4月更文挑战第30天】对比 Flutter(Dart,强类型,Google支持,快速热重载,高性能渲染)与 React Native(JavaScript,庞大生态,热重载,依赖原生渲染),文章讨论了开发语言、生态系统、性能、开发体验、学习曲线、社区支持及项目选择因素。两者各有优势,选择取决于项目需求、团队技能和长期维护考虑。参考文献包括官方文档和性能比较文章。
【Flutter前端技术开发专栏】Flutter与React Native的对比与选择
|
10天前
|
前端开发 自动驾驶 程序员
鸿蒙? 车载?Flutter? React Native? 为什么我劝你三思,说点不一样的
本文探讨了在信息技术快速发展的背景下,开发者如何选择学习路径。作者提倡使用终局思维来规划职业发展,考虑技术的长远影响。终局思维注重长远目标、系统分析、反向规划和动态调整。以车载开发为例,预测未来智能汽车可能由语音助手主导,而非依赖平板界面。此外,作者建议不要过分投入打工状态,应思考创建自己的产品,如App,以实现技能补充和额外收入。选择对未来发展和自主性有益的技术,如Kotlin,比盲目追求热点更为重要。做减法和有标准的选择,能帮助减轻焦虑,实现更高效的成长。关注公众号“AntDream”获取更多相关内容。
22 1
|
12天前
|
开发框架 前端开发 JavaScript
移动应用开发中的跨平台策略:Flutter与React Native的比较
在移动应用领域,跨平台解决方案已成为开发者追求高效、成本效益和广泛覆盖的关键。本文深入探讨了两种领先的跨平台框架——Flutter和React Native,从技术架构、性能、社区生态及实际应用案例四个维度进行全面对比分析。通过这一比较,旨在为移动应用开发者提供选择合适框架的参考依据,帮助他们根据项目需求做出明智的决策。
|
1月前
|
开发框架 移动开发 前端开发
【Uniapp 专栏】Uniapp 与 React Native 的对比分析
【5月更文挑战第14天】Uniapp和React Native是热门的跨平台移动开发框架。Uniapp以其一套代码多端运行、丰富的组件生态和较低的学习曲线受到青睐,适合快速开发简单应用。React Native基于React,拥有活跃社区和优秀性能,适合复杂应用。React Native在性能上略胜一筹,尤其在需要接近原生体验的场景。Uniapp的官方组件弥补了社区资源不足。选择时需考虑开发效率、性能需求、团队技术栈和社区支持。
【Uniapp 专栏】Uniapp 与 React Native 的对比分析
|
21天前
|
前端开发 iOS开发 Android开发
React Native跨平台开发实战:从零到一
学习React Native跨平台开发,首先安装Node.js和React Native CLI,设置Android/iOS环境。使用CLI创建项目,如`npx react-native init MyProject`。运行应用:`npx react-native run-android`或`run-ios`。编写组件,如在App.js中创建Hello World。添加样式,安装第三方库如react-native-vector-icons,使用react-navigation进行路由和导航。
23 2
|
2天前
|
Dart 前端开发 JavaScript
探索移动应用开发中的跨平台解决方案:Flutter与React Native的比较
在移动应用开发领域,选择合适的跨平台解决方案是关键。本文将深入分析Flutter和React Native这两大主流框架,从性能、开发效率、社区支持等方面进行比较,帮助开发者做出明智的选择。
12 0
|
1月前
|
前端开发 JavaScript Android开发
使用React Native开发跨平台移动应用的技术详解
【5月更文挑战第22天】本文详述了使用React Native开发跨平台移动应用的技术,该框架由Facebook推出,基于JavaScript,支持iOS和Android。React Native通过JNI/JSI实现JavaScript到原生代码的转换,提供高效性能和原生体验。其优势包括跨平台性、原生体验、开发速度及社区支持。开发流程涉及环境搭建、项目创建、编码、调试与测试,以及构建与发布。注意事项包括性能优化、平台适配、利用第三方库和持续学习。React Native为开发者构建高质量跨平台应用提供了便捷途径,未来潜力无限。
|
10天前
|
前端开发 JavaScript 算法
RSC 就是套壳 PHP ?带你从零实现 React Server Component
RSC 就是套壳 PHP ?带你从零实现 React Server Component
|
1月前
|
移动开发 前端开发 JavaScript
使用React Native进行跨平台移动开发
【5月更文挑战第13天】React Native是Facebook的跨平台移动开发框架,基于JavaScript和React,允许开发者编写原生应用。它提供跨平台性、原生性能、平缓的学习曲线及丰富的社区支持。开发流程包括安装CLI、创建项目、编写代码、运行调试及测试发布。进阶应用涉及状态管理、性能优化、原生模块集成和自动化测试。React Native降低了开发成本,提升了效率,是移动开发的优选方案。