• react 也就这么回事 05 —— 组件 & Props


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

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

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

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

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

    在线代码

    公众号【前端嘛】

  • 相关阅读:
    如何使用ZIP方式安装MySQL:简单、快速、高效的安装方法
    WPS前骨干历时10年打造新型软件,Excel用户:我为此改用WPS
    在命令行下使用Apache Ant
    简单工厂模式
    《Learning Hierarchical Modular Networks for Video Captioning》论文笔记
    LNK2001 无法解析的外部符号 cuGetErrorName解决
    前端项目实战189-根据id转化name
    java中的集合
    Flutter 使用Screen保持屏幕常亮不息屏
    【C语言】初识指针(终篇)
  • 原文地址:https://www.cnblogs.com/bidong/p/16003682.html