React是单向数据流
数据从父组件流向子组件。数据更新发送到父组件,父组件会进行实际的更改。
数据位于父组件中,并向下传递给子组件。虽然数据位于父组件中,但是父组件和子组件都可以使用数据。然而,如果必须更新数据的话,则只有父组件应该进行更新。如果子组件需要更改数据,它会将更新的数据发送给父组件,由父组件完成更改。父组件执行更改后,会将更新的数据传递给子组件。
听起来可能觉得带来了额外的工作量,但是让数据朝着一个方向流动并在一个位置修改使我们更容易理解应用的工作原理。
React和javascript的关系
React 的优势之一是你要用到的很多功能都使用的是普通的 JavaScript。在过去几年内,函数式编程对 JavaScript 生态系统和社区产生了很大的影响。函数式编程是 JavaScript 中一个高级课题,涉及的内容用数百本书才能讲完。它太复杂了,以至于无法专研函数式编程的优势(我们还是要讲解 React 内容吧?)。React 基于的是大量的函数式编程的技巧…你将在这门课程中学习这些技巧。但是,有几个 JavaScript 函数对函数式编程来说非常重要,我们应该了解这些函数。这些函数包括 .map() 和 .filter() 方法。
Array 的 .map() 方法
Array 的 .filter() 方法
在 React 中声明组件
1 | import React from 'react' |
在实际使用中, 可能还会看到下面的声明:
1 | import React, { Component } from 'react' |
创建元素总结
最后,记住 React 仅关心应用的 View 层级。这是用户能看见和互动的层级。因此,我们可以使用 .createElement() 向文档中渲染 HTML。但是更多时候,你将使用语法扩展来描述 UI 的外观应该如何。这种语法扩展称之为 JSX,看起来和编写在 JavaScript 文件中的普通 HTML 很像。JSX 编译为调用 React 的 .createElement() 方法,并输出要在浏览器中渲染的 HTML。
在构建 React 应用时一个便利的思维方式是React理念。组件代表的是 React 的模块性和可重复利用性。可以将组件类看做生成组件实例的工厂。这些组件类应该遵守单一功能原则,只做一件事。如果管理太多不同的任务,建议将组件拆分为更小的子组件。
create-react-app 总结
Facebook 的 create-react-app
是一个可以帮助构建 React 应用的命令行工具。借助该工具,就无需配置 Webpack 等模块打包工具,或者 Babel 等转译器。它们使用 create-react-app 进行预配置(并且隐藏起来),使你能够立即构建应用!
1 | npm install -g create-react-app |
https://github.com/udacity/reactnd-contacts-complete
利用props传递数据
我们可以认为向组件传递属性就像向函数传递参数。就像我们可以访问传入普通 JavaScript 函数的参数,我们也可以使用 this.props
(或者在无状态函数式组件中使用 props
)访问组件的属性。
使用 props 传递数据总结
props是传递给 React 组件的任何输入内容。就像 HTML 属性一样,props名称和值会添加到组件中。
// passing a prop to a component
在上述代码中,text 是props,字符串 ‘Wanna log out?’ 是值。
所有属性都存储在 this.props 对象上。因此,要在组件中访问此 text props,我们使用 this.props.text:
// access the prop inside the component
…
render() {
return{this.props.text}
}
…
函数式组件
无状态函数式组件。无状态意味着这些组件不用负责更改数据,只负责显示数据。如果组件仅使用
render
方法来显示内容,那么可以转换为无状态函数式组件。
可以直接通过传统function
来渲染组件,props
可直接作为参数而不需要用this
引出,例如:1
2
3
4
5
6
7
8
9function ListContacts(props) {
return (
<ol className='contact-list'>
{props.contacts.map((contact) => (
<li .... />
))}
</ol>
)
}
另外,React 组件只是返回要渲染的 HTML 的 JavaScript 函数。因此,下面的两个简单电子邮件组件示例是同等的:
1 | class Email extends React.Component { |
1 | const Email = (props) => ( |
React状态管理
状态是 React 组件的关键属性。熟悉状态的使用方法和设置(重置)方法将有助于简化应用 UI 构建流程。
状态总结
通过让组件管理自己的状态,任何时候该状态发生变化了,React 将知道并自动对页面做出必要的更新。
这是使用 React 构建 UI 组件的关键优势之一:如果要重新渲染页面,我们只需考虑更新状态。每次有更新时,我们不需要知道到底是页面的哪个部分变化了。我们不需要判断如何有效地重新渲染页面。React 会对比之前的输出和新的输出,判断哪些改变了,并为我们做出决策。这种判断之前的输出和新的输出之间哪些变化了的流程称为一致性比较。
使用setState更新状态
Your UI is just a function of your state
有两种方式来使用setState来更新
1)传入上一个状态作为参赛
1
2
3 this.setState((prevState) => ({
count: prevState + 1
}))
2)传入一个对象作为和上一个状态合并
1
2
3 this.setState({
username: 'Tyler'
})
最终,UI 只是状态的函数。在重置状态时,能够利用 React 的自动渲染功能使应用的用户真正获得了动态体验
引入PropTypes包来限定组件的属性类型
当我们向应用中实现更多的功能时,我们可能很快就发现经常需要调试我们的组件。例如,如果传递给组件的 props 不是期望的数据类型 (例如是对象,而不是数组),怎么办?PropTypes 是一个软件包,使我们能够在一开始就定义想要看到的数据类型,并且在开发过程中,如果传递给组件的属性不是我们预期的类型,PropTypes 将提醒我们。
要在应用中使用 PropTypes,我们需要安装 prop-types|(翻译):npm install --save prop-types
或者,如果你一直在使用 yarn 来管理包,那么你可以使用下面的命令来安装:yarn add prop-types
受控组件
借助受控组件,React 状态成为数据的“单一数据源”。
受控组件总结
受控组件是指渲染表格的组件,但是该表格状态的“数据源”位于组件状态里,而不是 DOM 里。受控组件的优势包括:
- 立即验证输入
- 有条件地停用/启用按钮
- 控制输入格式
对 React 状态的任何更改都将导致重新渲染页面内容,并有效地显示实时搜索结果。
React生命周期事件
componentWillMount: 组件插入DOM之前立即调用
componentDidMount: 组件插入DOM之后立即调用 (可用于Ajax异步加载API获取第三方数据时)
componentWillUnmount: 组件从DOM移除之前立即调用
componentWillReceiveProps: 组件即将接收全新的props时调用
render() 仅用于显示内容,我们将应该处理 Ajax 请求等任务的代码放在 React 的生命周期事件中。
componentDidMount() 的工作原理
在上一部分,我们提到 componentDidMount() 是组件添加到 DOM 之后立即运行的生命周期钩子,如果你想获取远程数据或发出 Ajax 请求,则应该使用该方法。以下是相关的 React 文档介绍:
componentDidMount() 在组件装载后立即被调用。应该在需要初始化 DOM 节点的时候使用该方法如果你想从远程端点加载数据,那么此处适合实现网络请求。在此方法中设置状态将触发重新渲染。
总结下,生命周期事件是 React 提供的特殊方法,使我们能够挂接到组件生命周期的不同阶段以运行一些代码。有各种不同的生命周期事件,它们将在不同的时间点运行,但是我们可以将它们划分为三大类别:
添加到 DOM 中
当组件正在被添加到 DOM 中时,这些生命周期事件被调用:1
2
3
4constructor()
componentWillMount()
render()
componentDidMount()重新渲染-rendering
当组件正在重新渲染到 DOM 时,这些生命周期事件被调用1
2
3
4
5componentWillReceiveProps()
shouldComponentUpdate()
componentWillUpdate()
render()
componentDidUpdate()从 DOM 中删除
当组件正在从 DOM 中被删除时,以下生命周期事件被调用1
componentWillUnmount()
下图表更清晰地了解所有这些方法都位于生命周期的哪个时间点