简单来说,props就是就是调用组件的时候传入的一个参数,它可以传入数据或方法(函数)。
这一节我们将要学习:
- 数据传入, 学习如何将数据传入并在组件内的render方法使用它。
- 数据验证, 学习在组件内使用
PropTypes包验证数据的有效性。
原始渲染
我们的目标只是简单的展示数据,选择class组件或函数组件其中之一即可。下面的示例将展示两种用法,最终显示的数据就是组件返回的JSX:
-
运行
git clone克隆开始项目:git clone https://github.com/softchris/react-starter-project demo-props cd demo-props该开始项目基于上一节的教程使用webpack配置react项目
-
运行
npm install命令安装依赖包:npm install
Class组件版本
-
在 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 文件中引入并调用该组件,定义一个数据变量并传进来。
-
在 index.js 文件中添加一行Project引入:
import Product from './Product'; -
在引入对象后加入一行对象定义:
const product = { name: 'Game Console' }; -
找到以下代码:
ReactDOM.render( <div>{title}</div>, document.getElementById('app') );做如下的修改,调用Product组件,传入一个对象数据:
ReactDOM.render( <Product data={product}/>, document.getElementById('app') ); -
在终端运行项目 npm start,查看修改是否生效:
npm start -
打开浏览器访问 http://localhost:8080. 查看结果:
Game Console输出的内容就是
Product组件返回的内容.注意数据赋值给了data并在调用Product组件时一起传入,组件返回的JSX结果显示到页面。
我们一起来回顾代码:
-
传入数据.
product对象赋值给了名为data的属性。注意我们使用了{}将数据包裹。在传入和解释数据的时候我们都会使用{}。 -
渲染数据. 在
render()方法中,传入的数据和标签一起组成JSX元素,并将它返回给调用者,完成数据渲染:this.props.data.name通过
this.prop访问所有传入的对象,通过点操作符访问指定的对象和name属性。
-
函数组件版本
我们也可以定义函数组件:
-
打开 Product.js 文件做以下修改:
import React from 'react'; const Product = (props) => <div>{props.data.name}</div> export default Product;文件保存后,webpack会重新编译项目.
-
使用浏览器查看结果 http://localhost:8080**:
Game Console成功!
与class组件一样,函数组件也需要 props,我们需要props来传递数据或函数。 在这里,Props 是传递给函数的参数,是组件的一部分。
渲染列表
渲染对象的时候,可以使用点操作符获取属性值并组成JSX返回。渲染列表也是类似的方法,不同的是需要使用map方法迭代处理列表里的项。
-
在 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 组件。、 -
在 index.js, 文件中引入和Cart组件:
import Cart from './cart';然后,为Cart组件准备列表数据.
-
在后边添加:
const products = [ { name: 'Game console' }, { name: 'Game' } ] -
找到如下代码:
ReactDOM.render( <Product data={product}/>, document.getElementById('app') );将它修改为:
ReactDOM.render( <Cart data={products}/>, document.getElementById('app') );文件保存后,webpack会重新编译项目.
-
使用浏览器查看结果 http://localhost:8080**:
查看结果:
Game console Game渲染列表成功.
使用PropTypes验证数据
随着我们的组件变得越来越复杂,我们希望确保组件正确。例如,如果一个组件有一个特定的属性集,我们就渲染它,如果属性集不正确,应该抛出一个错误。库 prop-types 帮助您定义哪些属性是必须的,并帮助定义它们的类型。
按照以下步骤:
- 下载, 使用npm 或 yarn下载.
- 引入,使用import引入.
- 配置. 配置组件的props包含的属性和类型.
-
运行以下代码下载安装:
npm install prop-types yarn add prop-types // 或者这个,取决于你使用的是 NPM 还是 Yarn -
打开 Product.js 组件并在文件头部添加引入:
import PropType from 'prop-types'; -
在组件export之前定义输入数据的验证要求:
Product.propTypes = { data : PropType.shape({ name: PropType.string.isRequired, }) };上面这段代码要求有一个data属性集。这是一个object/shape,包含一个 name 属性。
-
完整的代码如下:
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; -
为了演示验证是否生效,修改 index.js 传入数据:
const products = [ { name: 'Game console' }, { name: 'Game' } ]修改为:
const products = [ { name: 'Game console' }, { title: 'Game' } ]注意第二项属性修改为
title。这会使得prop-types验证失败。验证要求传入必须有Product的数据必须含有name属性。传入这段代码进Cart组件,您会发现一个错误。 -
运行项目
npm start:npm start -
打开浏览器访问 **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包验证数据有效性,有助于代码调试,尽早发现问题。