热门标签 | HotTags
当前位置:  开发笔记 > 开放平台 > 正文

React组件的三种写法总结

本文主要总结了React组件的三种写法以及最佳实践,具有一定的参考价值,下面跟着小编一起来看下吧

React 专注于 view 层,组件化则是 React 的基础,也是其核心理念之一,一个完整的应用将由一个个独立的组件拼装而成。

截至目前 React 已经更新到 v15.4.2,由于 ES6 的普及和不同业务场景的影响,我们会发现目前主要有三种创建 React 组件的写法:1. ES5写法React.createClass,2. ES6写法React.Component,3. 无状态的函数式写法(纯组件-SFC)。

你们最钟爱哪种写法呢?萝卜青菜各有所爱~ 每个团队都有自己的代码规范和开发模式,但书写 React 组件时 都会以提高代码阅读性、更优的组件性能、易于 bug 追踪为原则。下面我们就聊聊这三种写法的区别,以及各自所适用场景的最佳实践。

ES5-写法 React.createClass

React.createClass不用多说,我们最早使用这个方法来构建一个组件“类”,它接受一个对象为参数,对象中必须声明一个render方法,render返回一个组件实例,下面用一个 SwitchButton 组件的例子来看看React.createClass的具体用法:

var React = require('react');
var ReactDOM = require('react-dom');
var SwitchButton = React.createClass({
 getDefaultProp:function() {
 return { open: false }
 },
 getInitialState: function() {
 return { open: this.props.open };
 },
 handleClick: function(event) {
 this.setState({ open: !this.state.open });
 },
 render: function() {
 var open = this.state.open,
  className = open ? 'switch-button open' : 'btn-switch';

 return (
  
 );
 }
});
ReactDOM.render(
 ,
 document.getElementById('app')
);

ES6-写法 React.Component

React 升级到 v0.13 后就支持了 ES6 的class语法,我们可以使用class App extends React.Component{...}的方式创建组件,这也是目前官方推荐创建有状态组件的方式。用 ES6 重写上面 SwitchButton 组件的例子:

import React from 'react'
import { render } from 'react-dom'
class SwitchButton extends React.Component {
 constructor(props) {
 super(props)
 this.state = {
  open: this.props.open
 }
 this.handleClick = this.handleClick.bind(this)
 }
 handleClick(event) {
 this.setState({ open: !this.state.open })
 }
 render() {
 let open = this.state.open,
  className = open ? 'switch-button open' : 'btn-switch'
 return (
  
 )
 }
}
SwitchButton.defaultProps = {
 open: false
}
render(
 ,
 document.getElementById('app')
)

与React.createClass创建组件的不同之处:

import

与这里使用了 ES6 的import语句替代require()方法导入模块,其中import {render}可以直接从模块中导入变量名,这种写法更加简洁直观。

初始化 state

React 使用 ES6 的“类”继承实现时,去掉了getInitialState这个 hook 函数,state的初始化放在构造函数方法constructor中声明。

this 绑定

React.Component创建组件时,事件函数并不会自动绑定this,需要我们手动绑定,不然this将不会指向当前组件的实例对象。以下有三种绑定this的方法:

1. 在constructor中使用bind()进行硬绑定

constructor() {
 this.handleClick = this.handleClick.bind(this);
}

2. 直接在元素上使用bind()绑定

3. ES6 有个很有用的语法糖:Arrow Function(箭头函数)它可以很方便的使this直接指向class SwitchButton(它的作用等同于大家熟悉的var self = this,但后者会让代码变得混乱,Arrow Function 就很好的解决了这一问题)

无状态的函数式写法(纯组件 SFC)

React.createClass和React.Component都可以用来创建有状态的组件,而 无状态组件 - Stateless Component 是 React 在 v0.14 之后推出的。

它的出现 是因为随着应用复杂度不断提升和组件本数量的增加,组件按各自职责被分成不同的类型,于是有一种只负责展示的纯组件出现了,它的特点是不需要管理状态state,数据直接通过props传入,这也符合 React 单向数据流的思想。

对于这种无状态的组件,使用函数式的方式声明,会使得代码的可读性更好,并能大大减少代码量,Arrow Function 则是函数式写法的最佳搭档:

const Todo = (props) => (
 
  • {props.text}
  • )

    上面定义的 Todo 组件,输入输出数据完全由props决定,而且不会产生任何副作用。对于props为 Object 类型时,我们还可以使用 ES6 的解构赋值:

    const Todo = ({ onClick, complete, text, ...props }) => (
     
  • {props.text}
  • )

    无状态组件一般会搭配高阶组件(简称:OHC)一起使用,高阶组件用来托管state,Redux 框架就是通过 store 管理数据源和所有状态,其中所有负责展示的组件都使用无状态函数式的写法。

    这种模式被鼓励在大型项目中尽可能以简单的写法 来分割原本庞大的组件,而未来 React 也会面向这种无状态的组件进行一些专门的优化,比如避免无意义的检查或内存分配。所以建议大家尽可能在项目中使用无状态组件。

    当然,无状态组件也不是万金油,比如它不支持"ref",原因很简单,因为 React 调用它之前,组件不会被实例化,自然也就没有"ref",(ref和findDOMNode实际上打破了父子组件之间仅通过 props 来传递状态的约定,违背了 React 的原则,需要避免)。

    以上三种写法的比较,以及最佳实践

    Facebook 官方早就声明 ES6React.Component将取代React.createClass。随着 React 不断发展,React.createClass暴露出一些问题:

    • 相比React.Component可以有选择性的绑定需要的函数,React.createClass会自动绑定函数,这样会导致不必要的性能开销。
    • React.createClass亲生的 mixin,React.Component不再支持,事实上 mixin 不够优雅直观,替代方案是使用更流行的高阶组件-HOC,如果你的项目还离不开 也可以使用 react-mixin

    总的来说:无状态函数式写法 优于React.createClass,而React.createClass优于React.Component。

    以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持!


    推荐阅读
    • 实践指南:使用Express、Create React App与MongoDB搭建React开发环境
      本文详细介绍了如何利用Express、Create React App和MongoDB构建一个高效的React应用开发环境,旨在为开发者提供一套完整的解决方案,包括环境搭建、数据模拟及前后端交互。 ... [详细]
    • 本文提供了一个详尽的前端开发资源列表,涵盖了从基础入门到高级应用的各个方面,包括HTML5、CSS3、JavaScript框架及库、移动开发、API接口、工具与插件等。 ... [详细]
    • 2017年软件开发领域的七大变革
      随着技术的不断进步,2017年对软件开发人员而言将充满挑战与机遇。本文探讨了开发人员需要适应的七个关键变化,包括人工智能、聊天机器人、容器技术、应用程序版本控制、云测试环境、大众开发者崛起以及系统管理的云迁移。 ... [详细]
    • 开发笔记:[14]SQL 别名
      开发笔记:[14]SQL 别名 ... [详细]
    • SDWebImage第三方库学习
      1、基本使用方法异步下载并缓存-(void)sd_setImageWithURL:(nullableNSURL*)urlNS_REFINED_FOR_SWIFT;使用占位图片& ... [详细]
    • 探索UNIX操作系统的家族树
      通过回顾历史,我们可以更好地理解技术的发展。本文将带你深入了解UNIX操作系统的起源和发展历程,揭示其在现代计算中的重要地位。 ... [详细]
    • 大数据领域的职业路径与角色解析
      本文将深入探讨大数据领域的各种职业和工作角色,帮助读者全面了解大数据行业的需求、市场趋势,以及从入门到高级专业人士的职业发展路径。文章还将详细介绍不同公司对大数据人才的需求,并解析各岗位的具体职责、所需技能和经验。 ... [详细]
    • 美欧计划下周重启数据传输谈判
      据知情人士透露,欧盟法院去年夏天的一项裁决限制了企业将欧洲用户的个人信息传输至美国的方式。主要原因在于,法院认为欧洲客户在美国难以获得有效的法律保护。 ... [详细]
    • 本文介绍了实现人工智能的多种方法,并重点探讨了当前最热门的技术——通过深度学习训练神经网络。文章通过具体实例详细解释了神经网络的基本原理及其应用。 ... [详细]
    • 在2019中国国际智能产业博览会上,百度董事长兼CEO李彦宏强调,人工智能应务实推进其在各行业的应用。随后,在“ABC SUMMIT 2019百度云智峰会”上,百度展示了通过“云+AI”推动AI工业化和产业智能化的最新成果。 ... [详细]
    • Facebook开发先进AI系统,深入解析个人生活视角
      Facebook正大力投资于增强现实技术,与Ray-Ban合作开发AR眼镜。目前,这些设备主要用于图像的记录和分享,但公司展望未来,认为这些装置将具备更广泛的功能。一个由研究人员组成的团队正在开发先进的AI系统,旨在深入解析用户的个人生活视角,从而提供更加个性化的体验和服务。 ... [详细]
    • Presto:高效即席查询引擎的深度解析与应用
      本文深入解析了Presto这一高效的即席查询引擎,详细探讨了其架构设计及其优缺点。Presto通过内存到内存的数据处理方式,显著提升了查询性能,相比传统的MapReduce查询,不仅减少了数据传输的延迟,还提高了查询的准确性和效率。然而,Presto在大规模数据处理和容错机制方面仍存在一定的局限性。本文还介绍了Presto在实际应用中的多种场景,展示了其在大数据分析领域的强大潜力。 ... [详细]
    • PostgreSQL 与 MySQL 的主要差异及应用场景分析
      本文详细探讨了 PostgreSQL 和 MySQL 在架构、性能、功能以及适用场景方面的关键差异。通过对比分析,帮助读者更好地理解两种数据库系统的特性和优势,为实际应用中的选择提供参考。 ... [详细]
    • 巴比特 | 每日元宇宙精选:高端VR设备年销量突破千万,行业或将迎来转折点? ... [详细]
    • 题目要求将数字字符串转换为对应的字母组合,例如“111”可以转化为“AAA”、“KA”或“AK”。本文通过深入解析暴力递归方法,详细探讨了这一问题的解法,并结合真实的 Facebook 面试题目,提供了从左至右尝试模型的具体实现和优化策略。 ... [详细]
    author-avatar
    cz小屁孩865
    这个家伙很懒,什么也没留下!
    PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
    Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有