React笔记12(理念)

React理念

在我们的理念中,React最初的目的是适用javascript创建大型,快速响应的网络应用。它在我们的 Facebook 和 Instagram 中已经实践的非常好了。

React的众多优点之一是,它让你在编写代码的同时,也在思考这个应用。在这篇文档中,我们会使用 React 一起创建一个可搜索的产品数据表格,并向你展示我们的思考过程。

模拟页面

React笔记12(理念)_第1张图片
demo原型图

我们的 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划分到组件层级

第一件事情就是拆分组件,划分不同的组件并给他们命名。
哪一部分应该成为一个组件?
想想在编写代码时你在什么情况下需要新建一个函数或对象,思考方式是一样的。例如 单一功能原则,在理想状况下,一个组件应该只做一件事情。如果这个组件功能不断丰富,它应该被分成更小的组件。

React笔记12(理念)_第2张图片
组件划分

这里你会看到,我们的简单应用中有5个组件。我们把每个组件展示的数据用斜体表示。

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

如果你查看ProductTable,你会发现表头(包含name和price标签)并没有作为一个组件。这是一个偏好问题,选择哪种方式目前还存在争议,在这个例子中,我们把它作为ProductTable一部分,现在渲染数据集合,是ProductTable的职责,然而,如果头部变得更加复杂(比如添加排序功能)。这种情况下,就有理由称为一个单一的组件。

现在已经确定了原型图中组件,整理他的层级结构。
FilterableProductTable
1.SearchBar
2.ProductTable
3.ProductCategoryRow
4.ProductRow

用React创建一个静态版本

首先创建一个静态版本:
①传入数据模型
②渲染UI但是没有任何交互
③创建能复用其他组件的组件,并且通过props来传递数据
④可以自顶上下或者自底向上构建应用,也就是说可以从层级最高的组件开始FilterableProductTable,或层级最低的组件开始构建(ProductRow)。在简单的例子中,通常自顶向下更容易,在较大的项目中,自底向上会更加容易,并且有利于编写测试。
⑤在这步的最后,你会拥有一个用于呈现数据模型的可重用组件库。这些组件只会有 render() 方法,因为这只是你的应用的静态版本。层级最高的组件(FilterableProductTable)会把数据模型作为 prop 传入。如果你改变你的基础数据模型并且再次调用 ReactDOM.render(), UI 会更新。很容易看到你的 UI 是如何更新的,哪里进行了更新。因为没有什么复杂的事情发生。React 的单向数据流(也叫作单向绑定)保证了一切是模块化并且是快速的。

思考:props vs state

在React中,有2中数据模型:props和state,理解两种的区别是很重要的。

定义UI状态的最小表示

为了让UI产生变化,你需要能够触发底层数据模型的更改,React使用state,能让修改更加容易。
为了正确构建你的应用,首先需要考虑你的应用的最小可变状态集合。

比如现在需要完成一个todo列表
只需要保存一个包含todo事项的数组,不需要为计数保留一个单独的状态变量。相反当你想要渲染他的数量时候,只需要判断他的长度就可以了。
总结:能简单就简单,尽量少保存内容。

回顾实例应用中的所有数据:
①原产品列表
②用户输入搜索文本
③复选框的值
④产品的筛选列表

根据以上条目,找出哪一个放置state,每个数据都需要考虑3个问题。
①他的数据是通过props父级传递过来的吗,如果是,他就可能不是state。
②他会改变吗?如果不改变,他可能不是state
③你会根据组件中其他state、props把它计算出来吗,如果可以,他不是state
通常数据的源头是作为state

分析:

原产品列表被作为props传入,所以他不是state,搜索文本和复选框似乎是state,因为他们不会随着时间改变而改变内容,并且他们的内容是不能通过其他的值计算出来的。最后,产品筛选列表也不是state,因为他可以通过原产品列表以及搜索框的输入值搜索计算出来。

最后我们得出,state的值有,用户输入的文本,和复选框的值。

确定state应该位于哪里

现在state已经确定,接下来需要确定那个组件会改变,或者说拥有这个state。
注意:React中的数据是单向的,并且在组件层次中向下传递的。一开始我们经常不清楚,哪个组件应该拥有哪个state,新手理解这块内容通常是最有挑战性的部分。大致可以按照下面列举出来的东西来辨别。

针对你应用的每一个state:

①确定选择出每一个主要这个state来渲染数据的组件
②找到一个公共的所有者组件(一个层级上高于其他需要这个state的组件,也就是状态提升后其他组件距离最近的父组件)
③这个公共所有组件或者层级更高的一个组件应该拥有这个state
④如果此时还没有适合拥有state的组件,可以创建一个只是用来保存状态数据的组件,并且将它加入到比这个公共所有组件层级更高的地方。等于手动创建一个新的公共所有组件来控制他们的数据和展示。

使用以上的策略进行分析:

①ProductTable(用户搜索得出的筛选产品列表)是需要state数据过滤后得出的数据渲染该板块。
②SearchBar需要展示搜索的文本信息和复选框的状态。
③比他们层级更高且可以作为公共组件的是FilterableProductTable
④所以筛选文本和复选框的值应该放在FilterableProductTable组件中。
⑤所以,我们决定把state放在FilterableProductTable中。

第一:在FilterableProductTable组件中的构造函数constructor中添加一个实例属性this.state = {filterText: '', inStockOnly: false}来作为我们的初始状态,默认搜索文本为空,checkboxfalse
第二:将filterTextinDtockOnly作为prop属性向下分别传递给ProductTableSearchBar
第三:在ProductTable中使用得到的props属性值来筛选产品的信息。并且在SearchBar中设置表单域的值。

现在就能够明白你的应用是如何运作的了:设置 filterText 的值为 ball 并刷新你的应用。你会看到数据表格正确的更新了。

添加反向数据流

目前我们已经创建了一个可以正确渲染数据的应用了。他在数据的层级中通过props和state向下流动。现在我们尝试其他方式的数据流:层级关系中最底层的表单组件去更新最顶层FilterableProductTable中的state。

React的数据流很明显,可以清楚的明白应用是怎么运行的。相比较传统的双向绑定,代码会相对多一些。

当前的版本中,如果视图键入或者选择复选框。React会忽略你的输入,这是故意的。因为我们把 inputvalue 属性设置为一直等于从 FilterableProductTable 传入的 state。

我们需要做些什么

①确保每当用户修改表单的时候,更新状态来反应用户的输入。
②因为组件只会更新自己的状态,FilterableProductTable会将一个回调函数传递给SearchBar,每次当状态应该变化的时候就会触发。我们可以使用onChange事件来调用他。
③FilterableProductTable 传入的回调函数会调用 setState(),这时应用程序会被更新。

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

你可能感兴趣的:(React笔记12(理念))