[React Native] React 中的组件和属性(Components and Props)

目录

  • 1.组件(Components)
    • 1.1 什么是组件
    • 1.2 定义组件
    • 1.3 渲染组件
    • 1.4 组合组件
    • 1.5 封装组件
  • 2.属性(Props)

1. 组件(Components)

1.1 什么是组件

组件能让你将 UI 拆分成各个独立的、可复用的子单元。组件就像 JavaScript 函数一样,接受参数(也就是 props),返回屏幕上要渲染的 React 元素。各个组件内部维护自己的状态和 UI,当状态发生改变时,React 会自动重新渲染整个组件,多个组件一起协作共同构成了 React 应用。

1.2 定义组件

① 以函数的形式来定义组件

          function Welcome(props) {
              return <h1>Hello, {props.name}</h1>;
          }

② 以类(ES6 class)的形式来定义组件

         class Welcome extends React.Component {
             render() {
                 return <h1>Hello, {this.props.name}</h1>;
             }
         }

1.3 渲染组件

组件可以当作 React 元素来用。而且我们可以通过 Props 来向组件中传递参数:

         function Welcome(props) {
             return <h1>Hello, {props.name}</h1>;
         }

        const element = <Welcome name="Sara" />;
        ReactDOM.render(
          element,
          document.getElementById('root')
        );

1.4 组合组件

组件可以互相引用,一个组件中可以在标签中使用其他组件。

例如, App 组件中就有三个 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')
);

1.5 封装组件

通过将可重用的代码封装成一个独立的组件,可以提高代码的复用性和可读性。

什么时候需要封装组件?
① 大量的重复 UI 代码;
② 一个组件内部有太多的内容,相当复杂时,就需要抽取一部分代码出来。

举个例子,我们现在有一个 Comment 组件,通过 props 接收了三个参数 author (object), text (string), 和 date (date) ,用来显示一条评论:

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>
  );
}

很显然,这里的代码嵌套太多,难以阅读,而且里面的一些代码不能被重用。所以,我们可以尝试抽取一些代码进行组件封装。
第一步,我们先封装一个 Avatar 组件:

function Avatar(props) {
  return (
    <img className="Avatar"
      src={props.user.avatarUrl}
      alt={props.user.name}
    />
  );
}

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>
  );
}

即便这样,Comment 中的代码感觉还是有点多,我们还可以再进一步抽取封装一个 UserInfo 组件:

function UserInfo(props) {
  return (
    <div className="UserInfo">
      <Avatar user={props.user} />
      <div className="UserInfo-name">
        {props.user.name}
      </div>
    </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>
  );
}

2. 属性(Props)

什么是属性?大多数组件在创建时就可以使用各种参数来进行定制,用于定制的这些参数就称为属性(props)。

属性是用来给外部向组件内部传值的,组件的内部通过读取 props 来决定如何展示以及处理一些逻辑。

属性是只读的,不要试图在组件内部修改外部传递进来的 props。

React 组件就像 pure function 一样(不可以修改传入的参数):

// This is a pure function
function sum(a, b) {
  return a + b;
}

而不像 impure function(可以修改传入的参数):

// This function is impure because it changes its own input.
function withdraw(account, amount) {
  account.total -= amount;
}

关于 props 使用的完整示例代码:

import React, { Component } from 'react';
import { AppRegistry, Text, View } from 'react-native';

class Greeting extends Component {
  render() {
    return (
      <Text>Hello {this.props.name}!</Text>
    );
  }
}

class LotsOfGreetings extends Component {
  render() {
    return (
      <View style={{alignItems: 'center'}}>
        <Greeting name='Rexxar' />
        <Greeting name='Jaina' />
        <Greeting name='Valeera' />
      </View>
    );
  }
}

AppRegistry.registerComponent('LotsOfGreetings', () => LotsOfGreetings);

规则:

  1. 组件名必须以大写字母开头。
  2. 所有的 React 组件都必须想 pure function 一样对待它的 props——不要在组件内部修改 props。
  3. 组件必须返回一个单独的根元素。就像在上文中 4.1 部分的示例代码一样,App 组件返回时,通过一个 <div> 标签将 3 个 < Welcome /> 标签包起来了。

延伸阅读:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容