3

react 也就这么回事 05 —— 组件 & Props - 蜜瓜

 2 years ago
source link: https://www.cnblogs.com/bidong/p/16003682.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

什么是组件:用来实现局部功能的可复用代码片段

比如很多界面会用到“分页”功能,因此可以将它封装成独立的组件

这样用到分页的界面只需引入该组件而不必重新写代码

1 定义组件#

在 React 中有两种组件,一种是函数组件,一种是类组件

1.1 函数组件#

定义组件最简单的方式就是编写 JavaScript 函数

对 React 来说,能够返回一个 React 元素的 函数 就叫组件

function MyComponent() {    return <h2>我是一个函数组件</h2>;}

在线代码

1.2 class 组件#

类组件的声明过程会比较繁琐一些,需要使用 class、extends 关键字,来继承React.Component{}

render()函数会返回该类的实例要创建的元素。

class MyComponent extends React.Component {    render() {        return <h2>我是一个class组件</h2>;    }}

在线代码

无论是函数组件还是class组件,在 React 中是等效的,不过 class 组件有更多的特性

2 渲染组件#

同一个组件在不同界面使用,可能会想要展示不同的内容

比如我们自定义的组件包含了一个h2标签,如果我们想要在两个不同的界面分别展示函数class怎么办?

可以在使用组件时添加属性,react 会将添加的属性转换为一个对象传递给组件,这个对象称为"props"

函数组件和class组件可以分别通过“形参”和实例属性来使用这个对象

function MyComponent(props) {    console.log(props)    return <h2>我是一个函数组件</h2>;}ReactDOM.render(    <MyComponent a="1" b="2" />,    document.getElementById("root"));
class MyComponent extends React.Component {    render() {        console.log(this.props);        return <h2>我是一个class组件</h2>;    }}ReactDOM.render(    <MyComponent a="1" b="2" />,    document.getElementById("root"));

两者输出同样的对象:

在线代码

于是我们可以传入不同的属性,来让组件呈现不同的内容:

function MyComponent(props) {    return <h2>我是一个{props.name}组件</h2>;} ReactDOM.render(    <MyComponent name="自定义函数" />,    document.getElementById("root"));

在线代码

这个例子中发生了这些事:

  1. 我们调用 ReactDOM.render() 函数,并传入 <MyComponent name="自定义函数" /> 作为参数。
  2. React 调用 MyComponent 组件,并将 {name: '自定义函数'} 作为 props 传入。
  3. MyComponent 组件将 <h2>我是一个自定义函数组件</h2> 元素作为返回值。
  4. React DOM 将 DOM 高效地更新为 <h2>我是一个自定义函数组件</h2>

3 注意点#

  • 组件名称必须以大写字母开头。

  • 传入属性值为字符串和数字的区别:

    数字:<MyComponent a={1} />

    字符串:<MyComponent a="1" />

  • 多个属性可以使用扩展运算符

    const obj = { name: 'React', age: 18 }<MyComponent {...obj} /> 

    注意{}不能省略

在线代码

3 组合组件#

组件可以在其输出中引用其他组件

例如,我们可以创建一个可以多次渲染 Welcome 组件的 App 组件:

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

这就可以让我们用同一组件来构建不同层次的新组件

在线代码

4 提取组件#

对于一个复杂的组件,我们应该尽量将其拆分为更小的组件,以提高其可维护性和可读性

例如,参考如下 Comment 组件:

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

该组件用于描述一个社交媒体网站上的评论功能,它接收 author(对象),text (字符串)以及 date(日期)作为 props。

该组件由于嵌套的关系,变得难以维护,且很难复用它的各个部分。因此,让我们从中提取一些组件出来。

首先,我们将提取 Avatar 组件:

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

Avatar 不需知道它在 Comment 组件内部是如何渲染的。因此,我们给它的 props 起了一个更通用的名字:user,而不是 author

建议从组件自身的角度命名 props,而不是依赖于调用组件的上下文命名。

现在可以在Comment中引用Avatar组件了:

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

接下来,我们将提取 UserInfo 组件,该组件在用户名旁渲染 Avatar 组件:

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

5 Props 的只读性#

对于 props,React 有一个严格的规则:

组件无论是使用函数声明还是通过 class 声明,都决不能修改自身的 props。

6 计时器#

function tick() {  const element = ( 		<h2>当前时间: {new Date().toLocaleTimeString()}.</h2>  );  ReactDOM.render(element, document.getElementById('root'));} setInterval(tick, 1000);

这个例子中,每秒调用一次 tick 函数,页面会更新当前时间

在线代码

将它封装为一个组件:

class Clock extends React.Component {  render() {    return <h2>现在时间:{new Date().toLocaleTimeString()}</h2>;  }} function tick() {  ReactDOM.render(<Clock />, document.getElementById("root"));} setInterval(tick, 1000);

我们将时间写死在了 JSX 中

在线代码

如果我们想自己传入显示的内容:

class Clock extends React.Component {  render() {    const time = this.props.time;    return <h2>现在时间:{time}</h2>;  }} function tick() {  ReactDOM.render(    <Clock time={new Date().toLocaleTimeString()} />,    document.getElementById("root")  );} setInterval(tick, 1000);

这样我们就可以控制显示的格式

在线代码

公众号【前端嘛】


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK