From 5f90dceb9c3d7e9053f9dfe8c4d51b576e5fa474 Mon Sep 17 00:00:00 2001 From: "Jay.M.Hu" Date: Fri, 14 Apr 2017 16:57:17 +0800 Subject: [PATCH] react component and props Former-commit-id: a25fef6719173822350511fdd3e4a4cd6597fbf2 Former-commit-id: 61d9a6492fdc31831d7c89097907e30cbf5ad7c6 --- ...66\344\270\216\345\261\236\346\200\247.md" | 255 ++++++++++++++++++ 1 file changed, 255 insertions(+) create mode 100644 "React\351\235\242\351\235\242\350\247\202/\343\200\220\350\257\221\343\200\221\345\277\253\351\200\237\350\265\267\346\255\245-\347\273\204\344\273\266\344\270\216\345\261\236\346\200\247.md" diff --git "a/React\351\235\242\351\235\242\350\247\202/\343\200\220\350\257\221\343\200\221\345\277\253\351\200\237\350\265\267\346\255\245-\347\273\204\344\273\266\344\270\216\345\261\236\346\200\247.md" "b/React\351\235\242\351\235\242\350\247\202/\343\200\220\350\257\221\343\200\221\345\277\253\351\200\237\350\265\267\346\255\245-\347\273\204\344\273\266\344\270\216\345\261\236\346\200\247.md" new file mode 100644 index 0000000..ae945d3 --- /dev/null +++ "b/React\351\235\242\351\235\242\350\247\202/\343\200\220\350\257\221\343\200\221\345\277\253\351\200\237\350\265\267\346\255\245-\347\273\204\344\273\266\344\270\216\345\261\236\346\200\247.md" @@ -0,0 +1,255 @@ +--- +title: 快速起步-组件与属性 +date: 2017-4-14 16:01:04 +version: 15.5.0 +--- + +# 组件与属性 + +组件允许您将UI拆分为多个独立的,可重用的部分。 + +概念上,组件就类似于 `JavaScript` 函数。它们接收任意的输入(`props`),返回用于描述屏幕显示内容的 `React elements`。 + +## 函数式组件和类组件 + +最简单定义组件的方式,是编写一个 `JavaScript` 函数: + +```js +function Welcome(props) { + return

Hello, {props.name}

; +} +``` +这个函数是一个合法的组件,因为它接收包含数据的单个 `props` 对象参数,返回了一个 `React elements`。我们称这种用JavaScript函数定义的组件为函数式组件。 + +你也可以使用 [ES6 class](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Classes) 来定义组件: + +```js +class Welcome extends React.Component { + render() { + return

Hello, {this.props.name}

; + } +} +``` + +上述两个组件在视图展示上是等同的。 + +在 [下一章节](【译】快速起步-状态和生命周期.md) 我们会讨论类组件的一些附加特性。在这之前,我们先使用函数式组件来简化演示。 + +## 渲染组件 + +之前,我们仅仅遇到表示DOM标签的 `React elements`: + +```js +const element =
; +``` + +然而,元素也可以表示用户定义的组件: + +```js +const element = ; +``` +当 `React` 发现元素表示一个用户定义的组件时,它将 `JSX` 属性作为单个对象传递给组件。我们称之为 `props`。 + +例如,以下代码在页面上渲染 "Hello, Sara": + +```js{1,5} +function Welcome(props) { + return

Hello, {props.name}

; +} + +const element = ; +ReactDOM.render( + element, + document.getElementById('root') +); +``` + +[CodePen Demo](http://codepen.io/gaearon/pen/YGYmEG?editors=0010) + +我们回顾下这个例子中发生了什么: + +1. 使用 `` 元素调用 `ReactDOM.render()`。 +2. React 将 `{name: 'Sara'}` 作为属性调用 `Welcome` 组件。 +3. `Welcome` 组件将 `

Hello, Sara

` 元素作为结果返回。 +4. React DOM 使用 `

Hello, Sara

` 来更新DOM。 + +>**警告:** +> +>总是用大写字母开头命名自定义组件 +> +>例如, `
` 表示一个DOM标签,但是 `` 表示一个组件,且需要作用域中存在 `Welcome` 变量。 + +## 复合组件 + +组件可以在其输出中引用其他组件。这使我们可以对不同级别的实现抽象为相同的组件。在 `React` 中,按钮、表单、对话框,屏幕都通常被抽象为组件。 + +例如,我们可以创建 `App` 组件来渲染多个 `Welcome` 组件: + +```js{8-10} +function Welcome(props) { + return

Hello, {props.name}

; +} + +function App() { + return ( +
+ + + +
+ ); +} + +ReactDOM.render( + , + document.getElementById('root') +); +``` + +[CodePen Demo](http://codepen.io/gaearon/pen/KgQKPr?editors=0010) + +通常,新的React应用程序在最顶层都会有一个 `App` 组件。然而,如果你集成 `React` 到一个现有的应用程序,你可以在内部先使用像 `Button` 这样的小部件,然后逐步的替换到最顶层。 + +>**警告:** +> +>组件必须返回单个根元素。这是为什么我们用 `
` 来包含多个 `` 组件。 + +## 提取组件 + +不要害怕将组件分成更小的组件。 + +例如,思考这个 `Comment` 组件: + +```js +function Comment(props) { + return ( +
+
+ {props.author.name} +
+ {props.author.name} +
+
+
+ {props.text} +
+
+ {formatDate(props.date)} +
+
+ ); +} +``` + +[CodePen Demo](http://codepen.io/gaearon/pen/VKQwEo?editors=0010) + +它接收 `author`(对象类型),`text`(字符串)和 `date`(日期) 作为属性,然后在社交网站上呈现一个评论。 + +由于多层嵌套,这个组件很难变化,且很难重用它其中的各个部分。我们可以从中提取几个组件。 + +首先,我们提取 `Avatar` 组件: + +```js{3-6} +function Avatar(props) { + return ( + {props.user.name} + ); +} +``` + +`Avatar` 不需要知道谁会渲染它。这也是为什么我们使用 `user` 这个更通用的属性名称来替代 `author`。 + +我们建议从组件自身的角度来命名属性,而不是它的使用者。 + +我们现在已经稍微简化了一下 `Comment` 组件: + +```js{5} +function Comment(props) { + return ( +
+
+ +
+ {props.author.name} +
+
+
+ {props.text} +
+
+ {formatDate(props.date)} +
+
+ ); +} +``` + +下一步,我们将提取 `UserInfo` 组件,用于在用户名旁边显示 `Avator`: + +```js{3-8} +function UserInfo(props) { + return ( +
+ +
+ {props.user.name} +
+
+ ); +} +``` + +这让我们进一步简化了 `Comment` 组件: + +```js{4} +function Comment(props) { + return ( +
+ +
+ {props.text} +
+
+ {formatDate(props.date)} +
+
+ ); +} +``` + +[CodePen Demo](http://codepen.io/gaearon/pen/rrJNJY?editors=0010) + +提取组件可能是看起来很繁琐的工作,但是在较大的应用程序中,可重用的组件能够付出更小的代价。 +如果您的UI的一部分使用了几次(按钮,面板,头像)或者它自身就很复杂(App, Comment),它们则是拆分出可重用组件的最佳候选人,这是一个相当实用的经验法则。 + +## 属性是只读的 + +当你定义一个组件时,它不应该修改自己的 `props`。思考下面的 `sum` 函数。 + +```js +function sum(a, b) { + return a + b; +} +``` + +这些不会修改输入参数,且当输入参数相同时,总是返回相同结果的函数被称之为 [纯函数](https://en.wikipedia.org/wiki/Pure_function)。 + +相比之下,以下的函数是不纯的,因为它改变了自己的输入: + +```js +function withdraw(account, amount) { + account.total -= amount; +} +``` + +`React` 非常灵活,但是也有一个严格的规则: + +**所有的React组件必须像纯函数那样使用 `props`(也就是不要在组件内部修改 `props`)** + +当然,应用程序的UI是动态的,可以随时间的推移而变化。在 [下一节](【译】快速起步-状态和生命周期.md) 中,我们将介绍新的概念 `state`。`state` 允许React组件根据用户操作,网络响应以及其他随时间推移产生的变化来修改组件输出,而不会违背该规则。 \ No newline at end of file