谈一谈创建React Component的几种方式

技术谈一谈创建React Component的几种方式 谈一谈创建React Component的几种方式当我们谈起React的时候,多半会将注意力集中在组件之上,思考如何将页面划分成一个个组件,以及如

谈谈创建反应组件的几种方法

当我们谈论React时,我们主要关注组件,思考如何将页面划分为组件以及如何编写可重用的组件。然而,对于那些短时间内没有真正用React完成一个完整项目的人来说,理解如何创建一个组件并不那么简单。一开始,我以为要创建一个组件,只需要调用api createClass。但是,在学习了ES6的语法之后,我知道我可以通过ExtensionReact使用继承来创建组件。组件。后来,在阅读其他人的代码时,我发现了PureComponent和通过返回JSX语句创建组件的方法,而根本没有继承。在下面的文章中,我们将逐一介绍这些创建组件的方法,分析它们的特点,以及如何选择使用哪种方法来创建组件。

几种方法

1.createClass

如果还没有使用ES6语法,要定义组件,只能使用React.createClass的助手来创建组件。这里有一个例子:

var React=required(' React ');

var helling=react . create class({ 0

propTypes: {

名字叫:react.proptypes.string//property支票

},

getDefaultProps:函数(){ 0

返回{

名称:“玛丽”//默认属性值

};

},

getInitialState:函数(){ 0

返回{ count : this . props . initial count };//初始化状态

},

handleClick:函数(){ 0

//用户点击事件的处理功能

},

render:函数(){ 0

返回h1Hello,{ this . props . name }/h1;

}

});

module.exports=问候语;

这段代码包含组件的几个关键组件。这样组件的道具和状态都是以对象属性的形式组合在一起的,其中默认的道具和初始状态是返回对象的函数,propTypes是对象。这里还有一个值得注意的地方,就是在createClass中,React把这个绑定到属性中的所有函数,也就是上面的hanleClick实际上相当于handleClick.bind(this)。

2.component

因为ES6支持语法级别的类和继承,所以用ES6创建组件的方式更加优雅。以下是一个例子:

从“React”导入React;

类问候语扩展了React。组件{

构造器(道具){ 0

超级(道具);

this . state={ count : props . initial count };

this . handleclick=this . handleclick . bind(this);

}

//静态defaultProps={

//name : ' Mary '//default props的另一种定义方式

//}

//静态propTypes={

//name: React。PropTypes.string

//}

handleClick(){ 0

//单击事件处理程序。

}

render(){ 0

返回h1Hello,{ this . props . name }/h1;

}

}

hello . ProTypeS={ 0

名称:反应。PropTypes.string

};

Greeting.defaultProps={

姓名: '玛丽'

};

导出默认变大;

我们可以看到问候语继承自React.component在构造函数中,父类的构造函数由super()调用。同时,我们可以看到组件的状态是通过在构造函数中分配this.state来实现的,而组件的道具是在类helling上创建的属性。如果您知道类的属性和对象的属性之间的区别,您可能会理解为什么会这样做。对于组件,组件的道具由父组件通过调用子组件传递给子组件。道具不应该在子组件内部修改。它更像是所有子组件实例的共享状态,不会因为子组件的内部操作而改变。因此,将道具定义为问候语类的属性更合理,而在表面。

向对象的语法中类的属性通常被称作静态(static)属性,这也是为什么props还可以像上面注释掉的方式来定义。对于Greeting类的一个实例对象的state,它是组件对象内部维持的状态,通过用户操作会修改这些状态,每个实例的state也可能不同,彼此间不互相影响,因此通过this.state来设置。

用这种方式创建组件时,React并没有对内部的函数,进行this绑定,所以如果你想让函数在回调中保持正确的this,就要手动对需要的函数进行this绑定,如上面的handleClick,在构造函数中对this 进行了绑定。

3.PureComponet

我们知道,当组件的props或者state发生变化的时候:React会对组件当前的Props和State分别与nextProps和nextState进行比较,当发现变化时,就会对当前组件以及子组件进行重新渲染,否则就不渲染。有时候为了避免组件进行不必要的重新渲染,我们通过定义shouldComponentUpdate来优化性能。例如如下代码:

class CounterButton extends React.Component {
  constructor(props) {
    super(props);
    this.state = {count: 1};
  }
  shouldComponentUpdate(nextProps, nextState) {
    if (this.props.color !== nextProps.color) {
      return true;
    }
    if (this.state.count !== nextState.count) {
      return true;
    }
    return false;
  }
  render() {
    return (
      button
        color={this.props.color}
        onClick={() = this.setState(state = ({count: state.count + 1}))}
        Count: {this.state.count}
      /button
    );
  }
}

shouldComponentUpdate通过判断props.colorstate.count是否发生变化来决定需不需要重新渲染组件,当然有时候这种简单的判断,显得有些多余和样板化,于是React就提供了PureComponent来自动帮我们做这件事,这样就不需要手动来写shouldComponentUpdate了:

class CounterButton extends React.PureComponent {
  constructor(props) {
    super(props);
    this.state = {count: 1};
  }
  render() {
    return (
      button
        color={this.props.color}
        onClick={() = this.setState(state = ({count: state.count + 1}))}
        Count: {this.state.count}
      /button
    );
  }
}

大多数情况下, 我们使用PureComponent能够简化我们的代码,并且提高性能,但是PureComponent的自动为我们添加的shouldComponentUpate函数,只是对props和state进行浅比较(shadow comparison),当props或者state本身是嵌套对象或数组等时,浅比较并不能得到预期的结果,这会导致实际的props和state发生了变化,但组件却没有更新的问题,例如下面代码有一个ListOfWords组件来将单词数组拼接成逗号分隔的句子,它有一个父组件WordAdder让你点击按钮为单词数组添加单词,但他并不能正常工作:

class ListOfWords extends React.PureComponent {
  render() {
    return div{this.props.words.join(',')}/div;
  }
 }
 
class WordAdder extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      words: ['marklar']
    };
    this.handleClick = this.handleClick.bind(this);
  }
  
  handleClick() {
    // 这个地方导致了bug
    const words = this.state.words;
    words.push('marklar');
    this.setState({words: words});
  }
  render() {
    return (
      div
        button onClick={this.handleClick} /
        ListOfWords words={this.state.words} /
      /div
    );
  }
}

这种情况下,PureComponent只会对this.props.words进行一次浅比较,虽然数组里面新增了元素,但是this.props.words与nextProps.words指向的仍是同一个数组,因此this.props.words !== nextProps.words 返回的便是flase,从而导致ListOfWords组件没有重新渲染,笔者之前就因为对此不太了解,而随意使用PureComponent,导致state发生变化,而视图就是不更新,调了好久找不到原因~。

最简单避免上述情况的方式,就是避免使用可变对象作为props和state,取而代之的是每次返回一个全新的对象,如下通过concat来返回新的数组:

handleClick() {
  this.setState(prevState = ({
    words: prevState.words.concat(['marklar'])
  }));
}

你可以考虑使用Immutable.js来创建不可变对象,通过它来简化对象比较,提高性能。
这里还要提到的一点是虽然这里虽然使用了Pure这个词,但是PureComponent并不是纯的,因为对于纯的函数或组件应该是没有内部状态,对于stateless component更符合纯的定义,不了解纯函数的同学,可以参见这篇文章。

4.Stateless Functional Component

上面我们提到的创建组件的方式,都是用来创建包含状态和用户交互的复杂组件,当组件本身只是用来展示,所有数据都是通过props传入的时候,我们便可以使用Stateless Functional Component来快速创建组件。例如下面代码所示:

import React from 'react';
const Button = ({
  day,
  increment
}) = {
  return (
    div
      button onClick={increment}Today is {day}/button
    /div
  )
}
Button.propTypes = {
  day: PropTypes.string.isRequired,
  increment: PropTypes.func.isRequired,
}

这种组件,没有自身的状态,相同的props输入,必然会获得完全相同的组件展示。因为不需要关心组件的一些生命周期函数和渲染的钩子,所以不用继承自Component显得更简洁。

对比

createClass vs Component

对于React.createClassextends React.Component本质上都是用来创建组件,他们之间并没有绝对的好坏之分,只不过一个是ES5的语法,一个是ES6的语法支持,只不过createClass支持定义PureRenderMixin,这种写法官方已经不再推荐,而是建议使用PureComponent。

pureComponent vs Component

通过上面对PureComponent和Component的介绍,你应该已经了解了二者的区别:PureComponent已经定义好了shouldUpdateComponentComponent需要显示定义。

Component vs Stateless Functional component

  1. Component包含内部state,而Stateless Functional Component所有数据都来自props,没有内部state;

  2. Component包含的一些生命周期函数,Stateless Functional Component都没有,因为Stateless Functional component没有shouldComponentUpdate,所以也无法控制组件的渲染,也即是说只要是收到新的props,Stateless Functional Component就会重新渲染。

  3. Stateless Functional Component不支持Refs

选哪个

这里仅列出一些参考:

  1. createClass, 除非你确实对ES6的语法一窍不通,不然的话就不要再使用这种方式定义组件。

  2. Stateless Functional Component, 对于不需要内部状态,且用不到生命周期函数的组件,我们可以使用这种方式定义组件,比如展示性的列表组件,可以将列表项定义为Stateless Functional Component。

  3. PureComponent/Component,对于拥有内部state,使用生命周期的函数的组件,我们可以使用二者之一,但是大部分情况下,我更推荐使用PureComponent,因为它提供了更好的性能,同时强制你使用不可变的对象,保持良好的编程习惯。

内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/117960.html

(0)

相关推荐

  • HBase的目录是什么意思

    技术HBase的目录是什么意思小编给大家分享一下HBase的目录是什么意思,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!/hbase/.tmp

    攻略 2021年12月8日
  • HBase如何实现多租户

    技术HBase如何实现多租户这篇文章主要介绍了HBase如何实现多租户,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。多租户(multi-tenancy t

    攻略 2021年12月9日
  • sql无效字符执行sql语句报错的解决方法

    技术sql无效字符执行sql语句报错的解决方法本篇文章为大家展示了sql无效字符执行sql语句报错的解决方法,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。说起来惭愧,总是犯一些小

    攻略 2021年12月1日
  • Confluence怎么扩展内存

    技术Confluence怎么扩展内存这篇文章主要介绍了Confluence怎么扩展内存,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。背景:Confluen

    攻略 2021年11月17日
  • DG Broker如何搭建

    技术DG Broker如何搭建这篇文章主要介绍了DG Broker如何搭建,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。DG Broker搭建 1.环境说

    攻略 2021年11月16日
  • C#序列号的设计不重复的实现方法是什么

    技术C#序列号的设计不重复的实现方法是什么这篇文章主要介绍“C#序列号的设计不重复的实现方法是什么”,在日常操作中,相信很多人在C#序列号的设计不重复的实现方法是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操

    攻略 2021年11月26日