Reactjs入门官方文档(三)【components-and-props】

本文深入探讨了React中组件的概念及Props的使用方法,通过实例介绍了如何创建可重用的组件,并强调了Props的只读特性。

Components and Props

译自reactjs官方文档

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以响应用户动作,网络变化等.

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值