React 是一个采用声明式,高效而且灵活的用来构建用户界面的框架。
这样我们就拿到了一个很有趣的看起来像 XML/HTML 的标签。
我们定义的ShoppingList组件只会渲染一些内置的 DOM 组件(<div>等
),但是使用自定义的 React 组件也很简单,通过<ShoppingList/>
这样的标签你就可以在 React 当中调用整个 ShoppingList 组件。每个组件都是独立包装好的,这样也就方便你像搭积木一样组合各种组件来构建复杂的UI界面。
在使用JavaScript classes时,你必须调用super(); 方法才能在继承父类的子类中正确获取到类型的 this 。
当你遇到需要同时获取多个子组件数据,或者两个组件之间需要相互通讯的情况时,把子组件的 state 数据提升至其共同的父组件当中保存。之后父组件可以通过 props 将状态数据传递到子组件当中。这样应用当中的状态数据就能够更方便地交流共享了。
很轻松地实现 撤销/重做以及时间旅行
- 运用不可变性原则可以让我们很容易实现一些复杂的功能。
记录变化
运用不可变性原则之后则要轻松得多。因为我们每次都是返回一个新的对象,所以只要判断这个对象被替换了,那么其中数据肯定是改变了的。
在 React 当中判定何时重新渲染
运用不可变性原则给 React 带来最大的好处是,既然我们现在可以很方便地判断对象数据是否发生改变了,那么也就很好决定何时根据数据的改变重新渲染组件。尤其是当我们编写的都属于**
纯组件 pure components**
的时候,这种好处的效果更为明显。
React 专门为像Square组件这种只有 render 方法的组件提供了一种更简便的定义组件的方法: 函数定义组件 。只需要简单写一个以 props 为参数的 function 返回 JSX 元素就搞定了。
key是React当中使用的一种特殊的属性(除此之外还有 ref 属性)。当元素被创建时,React 会将元素的 key 值和对应元素绑定存储起来。尽管 key 看起来像是 props 的一部分,可是事实上我们无法通过 this.props.key 获取到 key 的值。React 会自动的在判断元素更新时使用 key ,而组件自己是无法获取到 key 的。
当一个列表被重新渲染时,React 会根据较新的元素内容依据相应的 key 值来匹配之前的元素内容。当一个新的 key 值添加到列表当中时,表示有一个组件被创建;被删除时表示有一个组件被销毁。Key 值可以让 React 明确标识每个组件,这样它才能在每次重新渲染时保有对应的状态数据。假如你去改变某个组件的 key 值的话,它会在下次渲染时被销毁并当作新的组件重新渲染进来。
强烈建议你在渲染列表项时添加 keys 值。 假如你没有现成可以作为唯一 key 值的数据使用的话,你可能需要考虑重新组织设计你的数据了。
假如你不提供任何 key 值,React 会提示警告,并且默认使用数组的索引作为默认的 key ,但只要你想在列表中对项目进行重新排列、添加或删除的话,这都不是一个好选择(因为对应的键值都会改变,也就会出现我们上面提到的组件key值被改变就会被当作新创建的组件处理那种情况)。手动添加列表索引值 key={i} 可以消除警告,但也会存在相同的问题,因此在大多数情况下都不推荐这种做法。
它被称为 JSX, 一种 JavaScript 的语法扩展。 我们推荐在 React 中使用 JSX 来描述用户界面。JSX 乍看起来可能比较像是模版语言,但事实上它完全是在 JavaScript 内部实现的。
我们书写 JSX 的时候一般都会带上换行和缩进,这样可以增强代码的可读性。与此同时,我们同样推荐在 JSX 代码的外面扩上一个小括号,这样可以防止 分号自动插入 的bug.
如果 JSX 标签是闭合式的,那么你需要在结尾处用 />, 就好像 XML/HTML 一样: 因为 JSX 的特性更接近 JavaScript 而不是 HTML , 所以 React DOM 使用 camelCase 小驼峰命名 来定义属性的名称,而不是使用 HTML 的属性名称
Babel 转译器会把 JSX 转换成一个名为*React.createElement()*的方法调用。 这样的对象被称为 “React 元素”。它代表所有你在屏幕上看到的东西。React 通过读取这些对象来构建 DOM 并保持数据内容一致。
与浏览器的 DOM 元素不同,React 当中的元素事实上是普通的对象,React DOM 可以确保 浏览器 DOM 的数据内容与 React 元素保持一致。
<div id="root"></div>
在此 div 中的所有内容都将由 React DOM 来管理,所以我们将其称之为 “根” DOM 节点。
我们用React 开发应用时一般只会定义一个根节点。但如果你是在一个已有的项目当中引入 React 的话,你可能会需要在不同的部分单独定义 React 根节点。
该函数是一个有效的React组件,它接收一个单一的“props”对象并返回了一个React元素。我们之所以称这种类型的组件为函数定义组件,是因为从字面上来看,它就是一个JavaScript函数。
当React遇到的元素是用户自定义的组件,它会将JSX属性作为单个对象传递给该组件,这个对象称之为“props”。 组件名称必须以大写字母开头。
例如,<div/>
表示一个DOM标签,但 <Welcome />
表示一个组件,并且在使用该组件时你必须定义或引入它。
组件的返回值只能有一个根元素。这也是我们要用一个<div>
来包裹所有<Welcome />
元素的原因。
所有的React组件必须像纯函数那样使用它们的props。
当然,应用的界面是随时间动态变化的,我们将在下一节介绍一种称为“state”的新概念,State可以在不违反上述规则的情况下,根据用户操作、网络响应、或者其他状态变化,使组件动态的响应并改变组件的输出。
只学习了一种方法来更新UI。
我们可以在组件类上声明特殊的方法,当组件挂载或卸载时,来运行一些代码: 这些方法被称作生命周期钩子。
当组件输出到 DOM 后会执行componentDidMount()
钩子,这是一个建立定时器的好地方。
状态更新可能是异步的
React 可以将多个setState()
调用合并成一个调用来提高性能。
因为 this.props
和 this.state
可能是异步更新的,你不应该依靠它们的值来计算下一个状态。
父组件或子组件都不能知道某个组件是有状态还是无状态,并且它们不应该关心某组件是被定义为一个函数还是一个类。 这就是为什么状态通常被称为局部或封装。 除了拥有并设置它的组件外,其它组件不可访问。
这通常被称为自顶向下或单向数据流。 任何状态始终由某些特定组件所有,并且从该状态导出的任何数据或 UI 只能影响树中下方的组件。
在 React 应用程序中,组件是有状态还是无状态被认为是可能随时间而变化的组件的实现细节。 可以在有状态组件中使用无状态组件,反之亦然。
框架通常是代码重用,而设计模式是设计重用,架构则介于两者之间,部分代码重用,部分设计重用,有时分析也可重用。
在软件生产中有三种级别的重用:
内部重用,即在同一应用中能公共使用的抽象块;
代码重用,即将通用模块组合成库或工具集,以便在多个应用和领域都能使用;
应用框架的重用,即为专用领域提供通用的或现成的基础结构,以获得最高级别的重用性。