Components and Props
Components帮助把UI分割成独立的,可重用的片段, 而我们只需要孤立的考虑每个片段.
在概念上, components就像javascript的函数, 它们接受任意的输入(称为props), 然后返回描述UI的React Elements
Components的函数式表达和类表达
定义一个component最简单的办法是通过javascript函数:
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
这个函数是一个有效的React component, 它接受一个单属性对象作为参数然后返回一个React element. 我们称这种对象是函数式的,因为他们字面上是javascript函数.
你也可以用ES6 class定义一个component:
“`javascript
class Welcome extends React.Component {
render() {
return
Hello, {this.props.name}
;}
}
上面两种表达在React看来是相等的
Classes有些其它功能将在下一节讨论, 在这之前我们使用简洁的函数式component.
### 渲染一个Component
在此之前我们只遇到过代表DOM元素的React elements:
```javascript
const element = <div />;
<div class="se-preview-section-delimiter"></div>
不过,elements也能表达用户自定义对象
const element = <Welcome name="Sara" />;
<div class="se-preview-section-delimiter"></div>
当React发现某个element代表了一个用户自定义component, 它将使用一个对象打包jsx属性传递给component, 我们称之为”props”
下面的例子将会在页面渲染”Hello Sara”:
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
const element = <Welcome name="Sara" />;
ReactDOM.render(
element,
document.getElementById('root')
);
<div class="se-preview-section-delimiter"></div>
我们回顾下这个例子里发生了什么:
1. 调用ReactDOM.render()渲染<Welcome name="Sara" />element.
2. React将{name: 'Sara'}作为props调用Weclome component.
3. Weclome component返回<h1>Hello, Sara</h1>element作为结果.
4. React 及时有效的更新DOM以匹配<h1>Hello, Sara</h1>.
警告:
component首字母大写.
例如,<div />代表一个DOM元素, 但<Welcom />代表一个component, 而且要求Welcome component在可见的定义域内.
复合Components
Components可以在他们的输出中引用其它的components, 这可以使我们在任何维度的抽象上使用同一个component. 按钮,表单,对话框: 在react应用中, 所有这些都使用components表达.
例如, 我们创建一个App component, 它简单的多次渲染Welcome:
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
function App() {
return (
<div>
<Welcome name="Sara" />
<Welcome name="Cahal" />
<Welcome name="Edite" />
</div>
);
}
ReactDOM.render(
<App />,
document.getElementById('root')
);
<div class="se-preview-section-delimiter"></div>
通常新的React应用只在最顶端有一个App component. 但如果你尝试在一个已存在的应用中引入React, 你可能会自下而上的从类似按钮这种小的component开始,逐渐按照你的方式完成集成.
警告:
Components必须返回一个单根元素, 所以在上面的例子中用一个div包裹了所有的<Welcome />elements.
抽象出Components
不要害怕把components拆分成更小的components.
比如下面这个Comment component:
function Comment(props) {
return (
<div className="Comment">
<div className="UserInfo">
<img className="Avatar"
src={props.author.avatarUrl}
alt={props.author.name}
/>
<div className="UserInfo-name">
{props.author.name}
</div>
</div>
<div className="Comment-text">
{props.text}
</div>
<div className="Comment-date">
{formatDate(props.date)}
</div>
</div>
);
}
<div class="se-preview-section-delimiter"></div>
它接受一个author对象,一个text字符串和date日期作为props,然后描述了社交网站上的一个评论.
这个component因为这些相互嵌套而难于修改, 而且难以复用其中某个部分, 让我们从中抽取出一些components.
首先是Avatar(头像):
function Avatar(props) {
return (
<img className="Avatar"
src={props.user.avatarUrl}
alt={props.user.name}
/>
);
}
<div class="se-preview-section-delimiter"></div>
这个Avata不需要知道它将被渲染到Comment. 这也是我们为什么给他的props一个更抽象的名字:user而不是author.
建议在props命名时站在components的视角而不是它将被用到的上下文的视角进行.
现在我们可以将Comment稍微简化一下:
function Comment(props) {
return (
<div className="Comment">
<div className="UserInfo">
<Avatar user={props.author} />
<div className="UserInfo-name">
{props.author.name}
</div>
</div>
<div className="Comment-text">
{props.text}
</div>
<div className="Comment-date">
{formatDate(props.date)}
</div>
</div>
);
}
<div class="se-preview-section-delimiter"></div>
接下来我们抽象出UserInfo component, 它包含一个Avata和用户名字:
function UserInfo(props) {
return (
<div className="UserInfo">
<Avatar user={props.user} />
<div className="UserInfo-name">
{props.user.name}
</div>
</div>
);
}
<div class="se-preview-section-delimiter"></div>
这使得Comment更加简洁:
function Comment(props) {
return (
<div className="Comment">
<UserInfo user={props.author} />
<div className="Comment-text">
{props.text}
</div>
<div className="Comment-date">
{formatDate(props.date)}
</div>
</div>
);
}
<div class="se-preview-section-delimiter"></div>
拆分出components的工作最初可能看起来有些繁琐, 但拥有一众可重用的components会使你在一个稍大的应用中游刃有余.
一条好的操作实践是,如果你UI的某个部分将被用到好多次,或者足够复杂, 使用可重用的component将是非常好的选择.
Props 是只读的
无论你使用函数式声明或者类声明一个component, 修改它的props都是禁止的.
试看下面的加和函数:
function sum(a, b) {
return a + b;
}
<div class="se-preview-section-delimiter"></div>
这种函数被称为无副作用的(pure),对应的impure函数:
function withdraw(account, amount) {
account.total -= amount;
}
React相当灵活但有一条严格的规则:
* 所有的React components必须是无副作用的, 即不可以修改传入的props对象. *
当然,应用的UI是动态的, 在下一节将引入一个新的概念”state”. State允许components在不违反这条规则的情况下返回不同的element以响应用户动作,网络变化等.
本文深入探讨了React中组件的概念及Props的使用方法,通过实例介绍了如何创建可重用的组件,并强调了Props的只读特性。
1004

被折叠的 条评论
为什么被折叠?



