React官方文档之React 理念

React 理念

在咱们的理念中,React 最初的目的是使用 JavaScript 建立大型的,快速响应的网络应用。它在咱们的 Facebook 和 Instagram 中已经实践的很是好了。css

React的众多优势之一是它让你在编写代码的时候同时也在思考你的应用。在这篇文档中,咱们会带你使用 React 一块儿建立一个可搜索的产品数据表格,并向你展现咱们的思考过程。html

从模拟页面开始

想象咱们已经有一个 JSON 接口和一个设计师给咱们的原型图。原型图像下面这样:react

Mockup

咱们的 JSON 接口返回相似下面的数据:数组

[
  {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 划分出组件层级

第一件你要作的事情是用方框划分出每个组件(和子组件)并给他们命名。若是你和设计师一块儿工做,他们可能已经完成了这些,因此去和他们聊聊吧!他们的 Photoshop 图层名称也许就是你的 React 组件名称!网络

但你如何知道哪一部分应该成为一个组件?想一想在编写代码时你在什么状况下须要新建一个函数或对象,思考方式是同样的。例如 单一功能原则,在理想情况下,一个组件应该只作一件事情。若是这个组件功能不断丰富,它应该被分红更小的组件。架构

既然你常常向用户展现 JSON 数据模型,你会发现,若是你的模型构建正确,你的 UI (以及你的组件结构)会被很好的映射。这是由于 UI 和数据模型每每遵循着相同的信息架构,这意味着将 UI 划分红组件的工做每每是很容易的。只要把它划分红能准确表示你数据模型的一部分的组件就能够。app

Component diagram

在这里你会看到,咱们的简单应用中有5个组件。咱们把每一个组件展现的数据用斜体表示。模块化

  1. FilterableProductTable (橙色): 包含了整个例子
  2. SearchBar (蓝色): 接受全部的用户输入
  3. ProductTable (绿色): 根据用户输入过滤并展现数据集合
  4. ProductCategoryRow (绿松石色): 展现每一个分类的标题
  5. ProductRow (红色): 用行来展现每一个产品

若是你查看 ProductTable,你会发现表头(包含 Name 和 Price 标签)并无做为一个组件。这是一个偏好问题,选择哪一种方式目前还存在争议。在这个例子中,咱们把它做为 ProductTable的一部分,由于它是渲染数据集合的一部分,而渲染数据集合是 ProductTable 的职责。然而,若是头部变得更加复杂(也就是,若是咱们添加了排序功能),它就有足够的理由成为一个单独的 ProductTableHeader 组件。函数

如今咱们已经肯定了原型图中的组件,让咱们把它们整理成层级结构。这很容易。原型图中的子组件在层级结构中应该做为子节点。测试

  • FilterableProductTable

    • SearchBar
    • ProductTable

      • ProductCategoryRow
      • ProductRow

第二步:用 React 建立一个静态版本

See the Pen Thinking In React: Step 2 on CodePen.

如今有了组件层级,是时候去实现你的应用了。最简单的方式是先建立一个静态版本:传入数据模型,渲染 UI 但没有任何交互。最好把这些过程解耦,由于建立一个静态版本更多须要的是码代码,不太须要逻辑思考,而添加交互则更多须要的是逻辑思考,不是码代码。咱们会看看为何是这样的。

要构建一个用于呈现数据模型的静态版本的应用程序,你须要建立可以复用其余组件的组件,并经过 props 来传递数据。props 是一种从父级向子级传递数据的方法。若是你熟悉 state 的概念, 在建立静态版本的时候不要使用 state。State 只在交互的时候使用,即随时间变化的数据。因为这是静态版本的应用,你不须要使用它。

你能够自顶向下或者自底向上构建应用。也就是,你能够从层级最高的组件开始构建(即 FilterableProductTable开始)或层级最低的组件开始构建(ProductRow)。在较为简单的例子中,一般自顶向下更容易,而在较大的项目中,自底向上会更容易而且在你构建的时候有利于编写测试。

在这步的最后,你会拥有一个用于呈现数据模型的可重用组件库。这些组件只会有 render()方法,由于这只是你的应用的静态版本。层级最高的组件(FilterableProductTable)会把数据模型做为 prop 传入。若是你改变你的基础数据模型而且再次调用 ReactDOM.render(), UI 会更新。很容易看到你的 UI 是如何更新的,哪里进行了更新。由于没有什么复杂的事情发生。React 的单向数据流(也叫做单向绑定)保证了一切是模块化而且是快速的。

若是你在这步须要帮助,请参阅 React 文档

一个小插曲:Props VS State

在 React 中有两种数据模型:props 和 state。理解二者的差异是很重要的;若是你还不肯定差异是什么,请查看React 官方文档

第三步:定义 UI 状态的最小(但完整)表示

为了使你的 UI 交互,你须要可以触发对底层数据模型的更改。React 使用 state,让这变的更容易。

为了正确构建你的应用,首先你须要考虑你的应用所须要的最小可变状态集。要点是 DRY:不要重复(Don’t Repeat Yourself)。找出应用程序的绝对最小表示并计算你所须要的其余任何请求。例如,若是你正在建立一个 TODO 列表,只要保存一个包含 TODO 事项的数组;不要为计数保留一个单独的状态变量。相反,当你想要渲染 TODO 计数时,只须要使用 TODO 数组的长度就能够了。

想一想咱们的实例应用中全部数据。咱们有:

  • 原产品列表
  • 用户输入的搜索文本
  • 复选框的值
  • 产品的筛选列表

让咱们来看看每一条,找出哪个是 state。每一个数据只要考虑三个问题:

  1. 它是经过 props 从父级传来的吗?若是是,他可能不是 state。
  2. 它随着时间推移不变吗?若是是,它可能不是 state。
  3. 你可以根据组件中任何其余的 state 或 props 把它计算出来吗?若是是,它不是 state。

原产品列表被做为 props 传入,因此它不是 state。搜索文本和复选框彷佛是 state,由于它们随时间改变而且不能由其余任何值计算出来。最后,产品的筛选列表不是 state,由于它能够经过将原始产品列表与搜索文本和复选框的值组合计算出来。

最后,咱们的 state 有:

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

第四步:肯定你的 State 应该位于哪里

See the Pen Thinking In React: Step 4 by Kevin Lacker (@lacker) on CodePen.

好的,如今咱们肯定了应用 state 的最小集合。接下来,咱们须要肯定哪一个组件会改变,或拥有这个 state。

记住:React 中的数据流是单向的,并在组件层次结构中向下传递。一开始咱们可能不是很清楚哪一个组件应该拥有哪一个 state。在新手理解上这一般是最富有挑战性的部分,因此按照下面的步骤来辨别:

对你应用的每个 state:

  • 肯定每个须要这个 state 来渲染的组件。
  • 找到一个公共全部者组件(一个在层级上高于全部其余须要这个 state 的组件的组件)
  • 这个公共全部者组件或另外一个层级更高的组件应该拥有这个 state。
  • 若是你没有找到能够拥有这个 state 的组件,建立一个仅用来保存状态的组件并把它加入比这个公共全部者组件层级更高的地方。

让咱们用这个策略分析咱们的应用:

  • ProductTable 须要根据 state 过滤产品列表,SearchBar 须要展现搜索文本和复选框状态。
  • 公共全部者组件是 FilterableProductTable
  • 筛选文本和复选框的值应该放在 FilterableProductTable

很酷,因此咱们决定把 state 放在 FilterableProductTable。首先,为 FilterableProductTable 的 constructor 添加一个实例属性 this.state = {filterText: '', inStockOnly: false} 来表示咱们应用的初始状态。接下来,把 filterText 和 inStockOnly 做为 prop 传入 ProductTable 和 SearchBar。最后在 ProductTable 中使用这些 props 来筛选每行产品信息,在 SearchBar 中设置表单域的值。

如今你可以看到你的应用是如何运做的了:设置 filterText 的值为 ball 并刷新你的应用。你会看到数据表格正确的更新了。

第五步:添加反向数据流

See the Pen Thinking In React: Step 5 on CodePen.

到目前为止,咱们已经建立了一个能够正确渲染的应用程序,它的数据在层级中经过函数的 props 和 state 向下流动。如今是时候支持其余方式的数据流了:层级结构中最底层的表单组件须要去更新在 FilterableProductTable 中的 state。

React 的数据流很明显,让你能够很轻松的了解你的程序是如何运行的,但相较于传统的双向绑定,它的代码量会稍微多一点。

在当前版本的示例中,若是你试图键入或选中复选框,你会发现 React 会忽略你的输入。这是故意的,由于咱们把 input 的 value 属性设置为一直等于从 FilterableProductTable 传入的 state.

让咱们想一想咱们想要作什么。咱们想确保每当用户更改表单时,咱们更新状态来反应用户输入。由于组件应该只更新本身的状态, FilterableProductTable 会将一个回调函数传递给 SearchBar ,每当应该更新状态时,它就会触发。咱们可使用输入上的 onChange 事件来调用它。FilterableProductTable 传入的回调函数会调用 setState(),这时应用程序会被更新。

虽然这听起来很复杂,但它只是几行代码的问题。并且,你能够清楚地看出你的应用中数据是如何流动的。

就是这样

但愿这可让你了解如何使用 React 构建组件和应用程序。虽然这可能会比之前编写更多的代码,但请记住,代码是用来读的,这比写更重要,而且很是容易阅读这个模块化的,思路清晰的代码。当你开始构建大型组件库的时候,你会开始欣赏 React 的思路清晰化和模块性,而且随着代码的复用,你的代码量会开始减小。:)

相关文章
相关标签/搜索