[React 2021新书]104、Props介绍

574 阅读6分钟

React新手村

简单来说,props就是就是调用组件的时候传入的一个参数,它可以传入数据或方法(函数)。

这一节我们将要学习:

  • 数据传入, 学习如何将数据传入并在组件内的render方法使用它。
  • 数据验证, 学习在组件内使用PropTypes包验证数据的有效性。

原始渲染

我们的目标只是简单的展示数据,选择class组件或函数组件其中之一即可。下面的示例将展示两种用法,最终显示的数据就是组件返回的JSX:

  1. 运行 git clone 克隆开始项目:

    git clone https://github.com/softchris/react-starter-project demo-props
    cd demo-props
    

    该开始项目基于上一节的教程使用webpack配置react项目

  2. 运行 npm install 命令安装依赖包:

    npm install
    

Class组件版本

  1. src 目录添加 Product.js 文件,并添加以下内容:

    import React from 'react';  
    
    class Product extends React.Component {
       render() {
         return (
           <div>{this.props.data.name}</div>
         );
       }
     }
     export default Product;
    

    我们将在 index.js 文件中引入并调用该组件,定义一个数据变量并传进来。

  2. index.js 文件中添加一行Project引入:

    import Product from './Product';
    
  3. 在引入对象后加入一行对象定义:

    const product = {
      name: 'Game Console'
    };
    
  4. 找到以下代码:

    ReactDOM.render(
      <div>{title}</div>,
      document.getElementById('app')
    );
    

    做如下的修改,调用Product组件,传入一个对象数据:

    ReactDOM.render(
     <Product data={product}/>,
     document.getElementById('app')
    );
    
  5. 在终端运行项目 npm start,查看修改是否生效:

    npm start
    
  6. 打开浏览器访问 http://localhost:8080. 查看结果:

    Game Console
    

    输出的内容就是 Product 组件返回的内容.

    注意数据赋值给了data并在调用Product组件时一起传入,组件返回的JSX结果显示到页面。

    我们一起来回顾代码:

    • 传入数据. product 对象赋值给了名为data的属性。注意我们使用了 {} 将数据包裹。在传入和解释数据的时候我们都会使用 {}

    • 渲染数据. 在 render() 方法中,传入的数据和标签一起组成JSX元素,并将它返回给调用者,完成数据渲染:

      this.props.data.name
      

      通过this.prop访问所有传入的对象,通过点操作符访问指定的对象和name属性。

函数组件版本

我们也可以定义函数组件:

  1. 打开 Product.js 文件做以下修改:

    import React from 'react';
    
    const Product = (props) => <div>{props.data.name}</div>
    
    export default Product;
    

    文件保存后,webpack会重新编译项目.

  2. 使用浏览器查看结果 http://localhost:8080**:

    Game Console
    

    成功!

    与class组件一样,函数组件也需要 props,我们需要props来传递数据或函数。 在这里,Props 是传递给函数的参数,是组件的一部分。

渲染列表

渲染对象的时候,可以使用点操作符获取属性值并组成JSX返回。渲染列表也是类似的方法,不同的是需要使用map方法迭代处理列表里的项。

  1. src 目录添加 Cart.js 文件,并添加以下内容:

    import React from 'react';
    import Product from './Product';
    
    class Cart extends React.Component {
      render() {
        return (
          <div>{this.props.data.map( product => <Product data={product} />)}</div>
        );
      }
    }
    
    export default Cart;
    

    在上面的代码中,您的 return 语句由一个 JSX 表达式组成,该表达式使用 map() 函数插入 this.props.products

    {this.props.product.map( product => <Product data={product} />)}
    

    对于products中的每个项目,都会生成一个 JSX 语句。最终得到的是一个 元素列表。Product如何渲染参照之前创建的 Product 组件。、

  2. index.js, 文件中引入和Cart组件:

    import Cart from './cart';
    

    然后,为Cart组件准备列表数据.

  3. 在后边添加:

    const products = [
      {
        name: 'Game console'
      },
      {
        name: 'Game'
      }
    ]
    
  4. 找到如下代码:

    ReactDOM.render(
     <Product data={product}/>,
     document.getElementById('app')
    );
    

    将它修改为:

    ReactDOM.render(
     <Cart data={products}/>,
     document.getElementById('app')
    );
    

    文件保存后,webpack会重新编译项目.

  5. 使用浏览器查看结果 http://localhost:8080**:

    查看结果:

    Game console
    Game
    

    渲染列表成功.

使用PropTypes验证数据

随着我们的组件变得越来越复杂,我们希望确保组件正确。例如,如果一个组件有一个特定的属性集,我们就渲染它,如果属性集不正确,应该抛出一个错误。库 prop-types 帮助您定义哪些属性是必须的,并帮助定义它们的类型。

按照以下步骤:

  • 下载, 使用npm 或 yarn下载.
  • 引入,使用import引入.
  • 配置. 配置组件的props包含的属性和类型.
  1. 运行以下代码下载安装:

    npm install prop-types
    yarn add prop-types // 或者这个,取决于你使用的是 NPM 还是 Yarn
    
  2. 打开 Product.js 组件并在文件头部添加引入:

    import PropType from 'prop-types';
    
  3. 在组件export之前定义输入数据的验证要求:

    Product.propTypes = {
      data : PropType.shape({
        name: PropType.string.isRequired,
      })
    };
    

    上面这段代码要求有一个data属性集。这是一个object/shape,包含一个 name 属性。

  4. 完整的代码如下:

    import React from 'react';
    import PropType from 'prop-types';
     
    const Product = (props) => <div>{props.data.name}</div>
     
    Product.propTypes = {
       data : PropType.shape({
         name: PropType.string.isRequired,
       })
    };
     
    export default Product;
    
  5. 为了演示验证是否生效,修改 index.js 传入数据:

    const products = [
       {
         name: 'Game console'
       },
       {
         name: 'Game'
       }
     ]
    

    修改为:

    const products = [
       {
         name: 'Game console'
       },
       {
         title: 'Game'
       }
     ]
    

    注意第二项属性修改为title。这会使得prop-types 验证失败。验证要求传入必须有 Product的数据必须含有name 属性。传入这段代码进Cart组件,您会发现一个错误。

  6. 运行项目 npm start:

    npm start
    
  7. 打开浏览器访问 **http://localhost:8080**.打开开发工具. 在Console调试窗口会看到红色的错误警告::

    Failed prop type: The prop `data.name` is marked as required in `Product`, but its value is `undefined`.
        at Product (webpack://webpack-app/./src/Product.js?:12:91)
        at Card (webpack://webpack-app/./src/cart.js?:38:5)
    

    验证成功!

    修改 index.js,把代码title改回name,错误提示就消失了。

最佳实践

使用PropTypes验证每一个输入数据被认为是最佳实践。此外,将 propTypes 作为class的成员移动到class内被认为是最佳实践,如下所示:

class Jedi extends React.Component {
  static propTypes = {
    jedi : PropType.shape({
      name: PropType.string.isRequired,
    })
  };

  render() {
    return (
      <div>Name: {this.props.jedi.name}</div>
    );
  }
}

上述代码会报错:

Support for the experimental syntax 'classProperties' isn't currently enabled (5:20)

Add @babel/plugin-proposal-class-properties (https://git.io/vb4SL) to the 'plugins' section of your Babel config to enable transformation.
If you want to leave it as-is, add @babel/plugin-syntax-class-properties 

该错误提示我们安装babel插件支持class Properties语法:

根据git.io/vb4SL 文档提示,按照以下步骤添加语法支持:

  • 下载, 使用npm 或 yarn下载.
  • 配置插件,在babel配置文件中添加支持.
  • 使用. 将 propTypes 作为class的成员移动到class内

1、在终端运行 npm install下载安装:

npm install --save-dev @babel/plugin-proposal-class-properties

2、打开.babelrc文件添加配置:

在babel配置文件中添加class-properties语法支持

{

  "presets": ["@babel/preset-env","@babel/preset-react"

  ],

  "plugins": ["@babel/plugin-proposal-class-properties"]

}

3、打开Product.js文件

将 propTypes 作为class的成员移动到class内,

import React from 'react';  
import PropType from 'prop-types';

class Product extends React.Component {
  static propTypes = {
    product : PropType.shape({
      name: PropType.string.isRequired,
    })
  };

  render() {
    return (
      <div>{this.props.data.name}</div>
    );
  }
}

export default Product;

示例

👉 查看示例代码

小结

学完props功能,我们来做一下总结。props是将数据传入组件的方式,其中包含以下知识点:

  • 在React调用组件时,设置属性传入数据 <Elem attr={data}>
  • 可以传入一个对象或列表.
  • 使用prop-types包验证数据有效性,有助于代码调试,尽早发现问题。