2019独角兽企业重金招聘Python工程师标准>>>

看到一篇无比蛋疼的文章:https://www.oschina.net/translate/exploring-reacts-state-propagation。我不针对翻译,只是针对这篇文章想提出的概念,说了跟没说一样,傻傻的。

要搞清楚React.js的props和state,必须要结合组件(组件类)从初始化到装载(mount)的过程来说。

组件类

假定我们通过以下的代码,创建了一个组件:

var SimpleComponent = React.createClass({getDefaultProps: function() {return {name: ''};},getInitialState: function() {return {};},render: function() {return <div>A simple component named {this.props.name}</div>;}
});

这里SimpleComponent是一个组件类。

组件虚拟对象

当我们要使用这个组件类的时候,可以写这样的代码:

<SimpleComponent name="abc"/>

实际上上述代码会转移成下面的js代码:

React.createElement(SimpleComponent, null)

通过React.createElement函数创建的,并不是SimpleComponent的组件类实例(即不是new SimpleComponent),而是一个不可写入的静态对象(Object),并且这个静态对象,具有props,没错,就是SimpleComponent组件类定义的getDefaultProps所返回的值。

我将这个静态对象称为组件虚拟对象,他持有了SimpleComponent的初始化所需的props,并且我有理由怀疑他是全局唯一的(当然我没精力去验证了)。

所以,要知道,当我们在jsx文件中,写了大量看似html标签的结构,他实际上并没有逐个创建对应的组件实例,取而代之的,仅仅是构造一大堆组件虚拟对象(静态Object)和传入参数而已。

注意,这个时候组件虚拟对象是没有state的。

组件实体(实例)

当一个组件虚拟对象被装载(mount)后——这里所谓装载,就是将一个或一大段组件虚拟对象插入到实际的DOM节点中时,才会创建出真实的组件实体(实例)。

创建组件的实体的时候,才会真正将调用参数传入(比如上面的name=abc),并且混入组件虚拟对象上的props。

当组件被实体化后,才真正的拥有state。

而我们实际在编写SimpleComponent这个组件类的方法时,都是假定针对的是组件实体的状态下进行的。

最后,总结为一个流程图来说明的话:

props只读、不可变?

我只能说,这是一个误区。首先,假定你拥有React Development tools的话,通过修改React.js的组件props,也能促使组件发生变化。就好像这样:

这个问题,仔细想想就能明白是别人给你挖了个坑(不是React.js,而是这些所谓的教程)。假定我们设计两个组件:

var AComponent = React.createClass({getDefaultProps: function() {return {name: ''};},getInitialState: function() {return {name: this.props.name};},render: function() {return <div>I'm {this.props.name}</div>;}
});var BComponent = React.createClass({getDefaultProps: function() {return {name: ''};},getInitialState: function() {return {name: this.props.name};},render: function() {return <div><AComponent name={this.state.name} /><button type="button" onClick={e => this.setState({name: 'Jack'})}>change name</button></div>;}
});

在B组件内,是使用state.name作为A组件的props.name传入的,如果是只读、不可变的话,那么B组件的按钮被点击后,B组件的state.name改变了,永远也不可能触发到A组件state更新了。

所以,严格来说,props不可变,只在组件虚拟对象这个阶段,因为那是一个不可写入的静态对象。

更进一步,从组件类到组件实例,实际上是完成了从props将数据传递给state。这是一个必然性的数据流向,无论多少次组件嵌套,这种数据流向都不会改变。所以一般而言,很少会去动(注意这里只是说动,但没有说不去读)一个组件实例的props,而直接操作state。

传统的OOP编程,并没有严格的数据流向,到底是属性到方法,还是方法到属性,还是属性到属性,完全由开发者自己掌控,你爱怎么写,就怎么写。这在前端组件的源码中,形成了很大的伪装性,当发生错误的时候,你完全不知道该从哪里开始着手,需要花一定的时间去解读、调试,然后才能定位问题(当然有好的规范可以相对的缓解类似的问题)。

而React.js则提供一种简单明确的机制(而且他只提供了这个机制而已),这也是React.js开发过程中会形成的一个思维定式。每当你开始编写一个组件,你就需要设计,这个组件应该具有哪些动态(交互性)特征需要放入state,而这些state又是怎么从props传递过去的。仅此而已,剩下的就是组件的界面逻辑开发而已。

state - 状态

这个应该不用多介绍了吧,React.js的卖点,组件实例的界面和自身的state动态结合,而且性能还相当的好。

不过其实这里也有一个小坑,就是当你在设计一个组件的时候,应该认真的思考哪些特征属于动态的。如果你在state里装载了大量的数据,要监控这些state的更新,还是相当的时间(其实真正很大的数据,大概会有3-5ms的延迟,但这个数据真的很大了)。所以,特别注意:

setState方法是异步的!!!

setState方法是异步的!!!

setState方法是异步的!!!

重要的事情说三次,是的,所以如果你这样写,可能会导致你的界面发生不可预料的后果:

this.setState(bigData);
// ...干点别的事情

正确的写法应该这样:

this.setState(bigData, function() {// ...干点别的事情
});

当你使用React.js开发的时间长了的话,慢慢的也会调整自己的思维方式,更加集中的设计state。这个下面还会提到。

es6 or typescript

如果可能的话,如果改用es6或者ts,上面的代码,将会简单很多很多:

class SimpleComponentES6 extends React.Component {constructor(props) {super(props);this.state = {name: this.props.name || ''}}render() {return <div>A simple component named {this.props.name}</div>;}
}

代码是不是顿时清晰了很多?

ts现在已经迈进2.0时代了,各方面都比过去完善了很多。假如你的项目,超过1000行JS,最好能换成ts,因为ts的语言特性,会让你的代码的自动提示得更加明确,而不像js或者es6,有的没的相似的不是的方法、属性提示你一大堆。

转载于:https://my.oschina.net/janpoem/blog/800002

React.js 组件的 props vs state相关推荐

  1. React简介、虚拟DOM、Diff算法、创建React项目、JSX语法、组件、组件声明方式、组件传值props和state、组件的生命周期

    React简介: 前面只是简单介绍移动APP开发,后面还会继续深入介绍移动app开发:其中想要用ReactNative开发出更出色的应用,那么就得学好React,下面将介绍React: React 是 ...

  2. 编写react组件_如何编写第一个React.js组件

    编写react组件 React的函数和类组件,道具,状态和事件处理程序 (React's function and class components, props, state, and event ...

  3. 移动web端的react.js组件化方案

     背景: 随着互联网世界的兴起,web前端开发的方式越来越多,出现了很多种场景开发的前端架构体系,也对前端的要求日益增高,早已经不是靠一个JQuery.js来做前端页面的时代了,而今移动端变化最大,近 ...

  4. React.js组件化开发第一步(框架搭建)

    开始前 安装 node.js; 安装 cnpm; 安装 yarn; 安装完成yarn后, 将镜像替换成国内的: $ yarn config set registry 'https://registry ...

  5. 如何在React JS组件和React JS App中添加CSS样式?

    In this tutorial, we will only work with CSS styles. Please ensure you have basic knowledge of HTML, ...

  6. [react] 在React中组件的props改变时更新组件的有哪些方法?

    [react] 在React中组件的props改变时更新组件的有哪些方法? 新版用 getDerivedstatefromProps(nextProps){ 业务逻辑} 个人简介 我是歌谣,欢迎和大家 ...

  7. React JS 组件间沟通的一些方法

    刚入门React可能会因为React的单向数据流的特性而遇到组件间沟通的麻烦,这篇文章主要就说一说如何解决组件间沟通的问题. 1.组件间的关系 1.1 父子组件 ReactJS中数据的流动是单向的,父 ...

  8. 【React】React三大属性:Props、State、Refs

    文章目录 Props State Ref Props React框架定义了一个Props的概念, 专门用来实现React组件接受参数的输入. 每个组件对象都会有props(properties的简写) ...

  9. react 子组件使用 props.history.push 无法跳转或者显示pushunderfind 问题

    出现这个问题的主要原因是在父组件里面没有给子组件传history 在我们的父组件里面传递一个history function MyModel(props) {return(<><Re ...

  10. (26)Vue.js组件通信—props 命名规则

    建议 prop 命名使用 camelCase(驼峰命名法),父组件绑定时使用 kebab-case(多个单词使用连字符连接书写).

最新文章

  1. 手语识别 机器学习_机器学习入门实践,让机器识别一只猫
  2. 一步步学习SPD2010--第七章节--使用BCS业务连接服务
  3. linux 安装postgres 全文检索支持
  4. 数据库执行sql报错Got a packet bigger than 'max_allowed_packet' bytes及重启mysql
  5. 文件压缩 ZipOutputStream类
  6. 你知道数据中台,但你肯定没听过报表中台,我靠它征服百万数据人
  7. 文章最重要的并不是原创,而是伪原创
  8. cookie httponly ajax,为什么jquery的.ajax()方法没有发送我的会话cookie?
  9. Imagination发布PowerVR软件开发套件和工具包重要更新版本,含光线追踪代码示例...
  10. 【数学】微分(Differential)的定义,微分与导数的区别
  11. 服务器没有显示器能接笔记本吗,笔记本能连显示器吗_笔记本能不能接显示器...
  12. php acs解密,RSA 加密及php实现
  13. 软件界面原型设计工具(Web):Axure RP
  14. 轻松搞定 Spring Cloud 2.x 微服务全家桶
  15. 【报错】安装scrapy时Could not build wheels for cryptography which use PEP 517 and cannot be installed direc
  16. P4408 [NOI2003] 树的直径
  17. Macbook外置移动硬盘安装win10教程
  18. Python scrapy环境搭建
  19. linux配置supervisor
  20. 安装了 Imagick(或者没有安装) 提示 Class ‘Imagick‘ not found

热门文章

  1. SQL Server游标使用快速上手
  2. 实例6 函数的返回值
  3. python学习笔记 day42 对数据表的操作---增删改查
  4. Python网络爬虫(四)
  5. finedb(内置的HSQL数据库)迁移数据到MySQL
  6. jquery 上下无缝滚动
  7. ASP.NET Web API 2基于令牌的身份验证
  8. codeigniter中base_url和site_url
  9. AD6.8_mcu123 分享地址
  10. 我所遭遇过的游戏中间件--Kynapse