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操作的次数,从而提高界面的渲染性能。

目录
相关文章
|
8天前
|
前端开发 UED 索引
React 图片灯箱组件 Image Lightbox
图片灯箱组件是一种常见的Web交互模式,用户点击缩略图后弹出全屏窗口展示大图,并提供导航功能。本文介绍了基于React框架的图片灯箱组件开发,涵盖初始化状态管理、图片加载与预加载、键盘和鼠标事件处理等常见问题及解决方案。通过`useState`和`useEffect`钩子管理状态,使用懒加载和预加载优化性能,确保流畅的用户体验。代码案例展示了组件的基本功能实现,包括打开/关闭灯箱、切换图片及键盘操作。
105 80
|
7天前
|
移动开发 前端开发 JavaScript
React 视频播放器组件:Video Player
本文介绍了如何使用 React 和 HTML5 `&lt;video&gt;` 标签构建自定义视频播放器组件。首先,通过创建基础的 React 项目和 VideoPlayer 组件,实现了基本的播放、暂停功能。接着,探讨了常见问题如视频加载失败、控制条样式不一致、性能优化不足及状态管理混乱,并提供了相应的解决方案。最后,总结了构建高效视频播放器的关键要点,帮助开发者应对实际开发中的挑战。
52 27
|
10天前
|
前端开发 JavaScript API
React 图片放大组件 Image Zoom
本文介绍如何使用React创建图片放大组件(Image Zoom),提升用户体验。组件通过鼠标悬停或点击触发放大效果,利用`useState`管理状态,CSS实现视觉效果。常见问题包括图片失真、性能下降和移动端支持,分别可通过高质量图片源、优化事件处理和添加触摸事件解决。易错点涉及状态管理混乱、样式冲突和过多事件绑定,建议使用上下文API、CSS模块及优化事件绑定逻辑。高级功能扩展如多张图片支持和自定义放大区域进一步丰富了组件的实用性。
43 25
|
6天前
|
存储 编解码 前端开发
React 视频上传组件 Video Upload
随着互联网的发展,视频内容在网站和应用中愈发重要。本文探讨如何使用React构建高效、可靠的视频上传组件,涵盖基础概念、常见问题及解决方案。通过React的虚拟DOM和组件化开发模式,实现文件选择、进度显示、格式验证等功能,并解决跨域请求、并发上传等易错点。提供完整代码案例,确保用户能顺畅上传视频。
118 92
|
11天前
|
移动开发 前端开发 JavaScript
React 图片裁剪组件 Image Cropper
本文介绍了在React中实现图片裁剪功能的方法,涵盖基础知识、常见问题及解决方案。首先,通过第三方库如`react-image-crop`或`cropperjs-react`可轻松实现图片裁剪。接着,针对性能和兼容性问题,提供了优化图片加载、处理裁剪区域响应慢、解决浏览器差异等方案。最后,通过代码案例详细解释了如何创建一个基本的图片裁剪组件,并提出了优化建议,如使用`React.memo`、添加样式支持及处理大图片预览,帮助开发者避免常见错误并提升用户体验。
94 67
|
1月前
|
前端开发 UED 开发者
React 悬浮按钮组件 FloatingActionButton
悬浮按钮(FAB)是常见的UI元素,用于提供突出的操作。本文介绍如何在React中使用Material-UI创建美观的FAB组件,涵盖基本概念、实现方法及常见问题解决。通过代码示例和优化技巧,帮助开发者提升用户体验,确保按钮位置、颜色、交互反馈等方面的表现,同时避免无障碍性和性能问题。
126 80
|
1月前
|
前端开发 JavaScript 开发者
React 按钮组件 Button
本文介绍了 React 中按钮组件的基础概念,包括基本的 `&lt;button&gt;` 元素和自定义组件。详细探讨了事件处理、参数传递、状态管理、样式设置和可访问性优化等常见问题及其解决方案,并提供了代码示例。帮助开发者避免易错点,提升按钮组件的使用体验。
201 77
|
1月前
|
存储 前端开发 UED
React 面包屑组件 Breadcrumb 详解
面包屑导航是现代Web应用中常见的UI元素,帮助用户了解当前位置并快速返回上级页面。本文介绍如何使用React构建面包屑组件,涵盖基本概念、实现方法及常见问题。通过函数式组件和钩子,结合React Router动态生成路径,处理嵌套路由,并确保可访问性。示例代码展示了静态和动态面包屑的实现,帮助开发者提升用户体验。
158 73
|
1月前
|
前端开发 UED 开发者
React 对话框组件 Dialog
本文详细介绍了如何在 React 中实现一个功能完备的对话框组件(Dialog),包括基本用法、常见问题及其解决方案,并通过代码案例进行说明。从安装依赖到创建组件、添加样式,再到解决关闭按钮失效、背景点击无效、键盘导航等问题,最后还介绍了如何添加动画效果和处理异步关闭操作。希望本文能帮助你在实际开发中更高效地使用 React 对话框组件。
142 75
|
16天前
|
前端开发 JavaScript UED
React 拖拽排序组件 Draggable List
在现代Web应用中,拖拽排序功能显著提升用户体验。使用React结合`react-dnd`库,可以轻松创建高效且易于维护的拖拽排序组件。通过简单的拖拽操作,用户能直观调整列表项顺序,适用于任务管理、看板工具等场景。实现步骤包括项目初始化、安装依赖、创建基础组件、添加拖拽功能及管理状态和事件。常见问题如拖拽效果不流畅、顺序未更新等可通过性能优化、正确处理索引交换等方式解决。移动端支持也需考虑,确保跨平台的良好体验。
78 25