React教程 - 12. React的编程思想

栏目: IOS · Android · 发布时间: 7年前

内容简介:React教程 - 12. React的编程思想

本文译自 React官方文档

全文翻译及相关代码,请参看 我的Github

从我们的角度来看,React是使用JavaScript构建大型、高效Web应用的首选,这在Facebook和Instagram中已经很好的证明了。

React最棒的部分之一在于-当我们构建我们的产品时,它会影响我们对产品的思考。在本部分,我们将引导您完成一个使用React构建某应用(一个可搜索的产品列表)的思考过程。

从视觉稿(Mock)开始

假设我们已经有一个JSON API和一个设计师的初稿,如图所示:

React教程 - 12. React的编程思想

JSON API返回的数据为:

[
  {category: "Sporting Goods", price: "$49.99", stocked: true, name: "Football"},
  {category: "Sporting Goods", price: "$9.99", stocked: true, name: "Baseball"},
  {category: "Sporting Goods", price: "$29.99", stocked: false, name: "Basketball"},
  {category: "Electronics", price: "$99.99", stocked: true, name: "iPod Touch"},
  {category: "Electronics", price: "$399.99", stocked: false, name: "iPhone 5"},
  {category: "Electronics", price: "$199.99", stocked: true, name: "Nexus 7"}
];

第一步-将UI分解至组件的层次结构中

我们首先会做的事是为视觉稿中的每个组件、子组件画框,并给他们命名。如果我们是和设计师一起工作的,他们可能已经完成了这部分内容。和他们交流一下,约定一下命名规范。他们在PS上给图层的命名可能最终成为我们React组件的名称。

但我们应如何拆分组件?把这当做拆分一个新方法或新对象吧。一个技巧是 单一职责原则 ,也就是说,理想情况下,一个组件只做一件事。若某个组件正变得越来越复杂,我们有必要对其进行进一步的拆分。

由于常常需要向用户展示JSON数据模型,若模型建立的正确,UI(以及组件结构)能够得到很好的映射。这是因为UI和数据模型往往拥有相同的信息结构,也就是说,将UI拆分成组件的工作通常比较琐碎。只需将其拆分成对应数据模型的片段即可。

React教程 - 12. React的编程思想

可以看到,在我们这个简单的应用中有5个组件,我们已经对每个组件代码的数据进行了标注。

  1. FilterableProducTable (橘色):包含整个实例。
  2. SearchBar (蓝色):接收所有的用户输入。
  3. ProductTable (绿色):基于用户的输入显示并过滤数据集合。
  4. ProductCategoryRow (宝石绿):显示每个类别的的标题。
  5. ProductRow (红色):按行显示每个产品的数据。
    ProductCategoryRow 为例子,我们可以发现包含”姓名”和”价格”的表头并不是独立的组件。这属于个人选择,也可以有别的方案。在本例中,将其作为 ProductTable 的一部分来处理,是因为其是数据集合渲染的一部分(这部分属于 ProductTable 的职责)。然而,若表头很复杂(如需要为其添加 排序 功能等),则将其拆分成一个 ProductTableHeader 组件是很有必要的。
    现在我们在视觉稿中标识出了我们的组件,现在让我们对他们进行层级排列。出现在A组件内部的组件B,就是A的子组件:
  • FilterableProducTable
    • SearchBar
    • ProductTable
      • ProductCategoryRow
      • ProductRow

第二步-在React中构建一个静态版本

有了组件的层次结构,是时候实现我们的APP了。最简单的方式是先建立一个“接受数据模型并渲染UI,但不存在交互”的版本。最好解耦这些处理-建立一个静态版本不需要思考太多,但添加交互往往需要考虑很多情况。

建立一个渲染数据模型的静态APP,需要构建复用其他组件并通过属性传递数据的组件。属性是一个从父组件向子组件传递数据的方法。如果您熟悉状态(state)的概念, 不要在这个静态版本的APP中使用state。 state只用于交互,也就是那些会随时变动的数据。由于这是个静态APP,我们不需要使用state。

我们可以自顶向下或自底向上构建应用。在构建简单的应用时,通常自顶向下更容易。在构建大型应用时,自底向上能够更方便与编写测试用例。

在这步结束时,我们已经有了一个可重用的,渲染数据模型的组件库。由于是个静态应用,这些组件只用 render() 方法。层级结构顶层的组件( FilterableProducTable )将接收数据模型作为一个属性(props)。当我们修改数据模型并再次调用 ReactDOM.render() 时,UI将同步更新。由于过程比较简单,观测UI的更新及相关数据的变化是非常方便的。React的 单向数据流 (也称为单向绑定)能够在开发过程中保证模块化和高性能。

第三步-确定UI状态(state)的最小(但完整的)表示

为了让UI变得可交互,我们需要能更改底层的数据模型。React通过state使这一过程变得容易。

为了正确的构架应用,我们首先要考虑的是应用需要的可变状态的最小集合。这里的关键是DRY(Don’t Repeat Yourself)原则。找出应用所需的最小的状态的集合,确保该状态集合可按需计算出应用的各状态。例如,若我们正在建立一个TODO列表,那么我们只要保留TODO元素数组即可,不需要用一个单独的state用于存储数组的长度(该数字可由数组得出)。

想想我们例子中的所有数据,我们有:

  • 产品的原始列表
  • 用户输入的搜索文本
  • 复选框的值
  • 过滤后的产品列表

让我们过一遍这些数据,确认那些属于state。我们可以通过三个问题进行判断:

  1. 其是否由父组件通过props传递-若是,其可能不是state
  2. 其是否是固定不变的-若是,其可能不是state
  3. 该值可通过其他state或props计算出来吗-若是,其可能不是state

产品的原始列表作为props传递,因此其不是state。用户输入的搜索文本和复选框的值看起来是state(他们会发生变化,且无法通过其他props/state计算得出)。最后,过滤后的产品列表不属于state-其可以通过产品的原始列表+用户输入的搜索文本+复选框的值计算得出。

所以,根据我们得到的结果,最终的state是:

  • 用户输入的搜索文本
  • 复选框的值

第四步-确定state的位置

我们在上一步确认了应用的最小state集合。接下来,要确定哪些组件是可变的。或者说,确定这些state的owner。

记住:React是自上而下的单向数据流层级。这也许会导致无法立即确定state应放在哪个组件比较合适。我们可以按照以下步骤进行确定:

对于应用中的每个state:

  • 确定每个基于该state渲染的组件
  • 找到公共的父组件(及所有需要该state组件的公共祖先组件)
  • 该state应置于公共父组件或更高层级的组件中
  • 若无法找到合适的放置state的位置,可创建一个新组件存储该state,并将这个新组件添加至公共父组件的上层
    将这个策略应用于我们的例子中:
  • ProductTable 需要机遇state过滤产品列表。 SearchBar 需要展示搜索文本和选中状态
  • 公共父组件为 FilterableProducTable
  • 从概念上来说,将过滤文本和选中的值置于 FilterableProducTable 是合适的
    综上,我们将state置于 FilterableProducTable 中。
    首先,添加一个实例属性 this.state = {filterText: '', inStockOnly: false}FilterableProducTable 的构造函数中,用于初始化程序的状态。
    然后,将 filterTextisStockOnly 作为props传递给 ProductTableSearchBar
    最后,使用这些props过滤 ProductTable 中的行,并设置表单字段中 SearchBar 的值。
    我们可以看一下我们应用的行为:在 filterText 中设置 "ball" 并刷新应用。我们可以看到数据被正确的更新了。

第五步-添加反向数据流

现在,我们已经构建了一个能够正确渲染、数据流从上至下的应用。是时候支持另一种反向的数据流方式了-层次结构中底层的form组件须有更新 FilterableProducTable 中的state。

React采用了明确的数据流向,使我们能够更轻松的理解程序的工作过程。但这也使得其相对于传统的双向数据绑定而言,在有些情况下需要多敲一些代码。

如果我们尝试在当前版本中修改复选框的内容,我们会发现React并未对其作出响应-这是有意为之的,我们已经设置了 inputvalue 的props由 FilterableProducTablestate 传递而来,使其始终保持一致。

那么我们想要的是什么呢?我们想保证无论用户何时修改表格中的内容,state都会及时更新并反映出这些变化。由于组件应该只能够更新他们自己的state, FilterableProducTable 将传递回调函数给 SearchBar ,这些回调函数在需要更新state时触发。我们可以将其绑定在onChange事件上接受通知。由 FilterableProducTable 传递的回调函数将调用 setState() ,从而应用程序会进行更新。

尽管这听起来很复杂,但其实只需少量的代码就能够实现。同时这能够清晰的展示应用中的数据流向。

写在最后

希望这能够给你一些在关于使用React构建组件和应用方法的想法。这种方法也许确实会让你比平时多写一些代码,但请记住,代码的可读性、模块性远比少写几行代码来的重要。当创建一个大型组件库时,您会感激这些结构清晰、模块化且可重用的代码:-)

本文首发于 http://www.miaoyunze.com/ ,转载请注明出处


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

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Android和PHP开发最佳实践

Android和PHP开发最佳实践

黄隽实 / 机械工业出版社华章公司 / 2013-3-20 / 79.00元

本书是国内第一本同时讲述Android客户端开发和PHP服务端开发的经典著作。 本书以一个完整的微博应用项目实例为主线,由浅入深地讲解了Android客户端开发和PHP服务端开发的思路和技巧。从前期的产品设计、架构设计,到客户端和服务端的编码实现,再到性能测试和系统优化,以及最后的打包发布,完整地介绍了移动互联网应用开发的过程。同时,本书也介绍了Android系统中比较有特色的功能,比如Go......一起来看看 《Android和PHP开发最佳实践》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具