第七章 react组件实例中三大属性之props

news/2024/7/15 19:01:53 标签: react.js, javascript, 前端, props

  React中的props是一种用于组件之间传递数据的机制。它是一个对象,包含了组件的属性和值。当一个组件被渲染时,它的props对象会被传递给它。这样,组件就可以使用这些属性来渲染自己。


案例分析

以下案例是展示一个人的信息。

<!-- 准备好员工“容器” -->
  <div id="app"></div>

  <!-- 引入ReactJS核心库 -->
  <script type="text/javascript" src="../JS/react.development.js"></script>

  <!-- 引入React-DOM核心库,用于操作DOM -->
  <script type="text/javascript" src="../JS/react-dom.development.js"></script>

  <!-- 引入Babel,用于编译jsx为js -->
  <script type="text/javascript" src="../JS/babel.min.js"></script>

  <!-- 此处类型为babel -->
  <script type="text/babel">
    class Person extends React.Component {
      state = {name:"Tom",sex:"man",age:"20"}
      
	render () {
        return (
          <ul>
            <li>name:{this.state.name}</li>
            <li>sex:{this.state.sex}</li>
            <li>age:{this.state.age}</li>
          </ul>
        )
      }
    }
    // 2、将虚拟DOM渲染到页面,标签必须闭合
   ReactDOM.render(<Person/>,document.getElementById('app'))
 </script>

此时页面展示的内容:

  • name:Tom
  • sex:man
  • age:20

以上组件的内容信息是使用状态(state)完成的,但是这样会出现一个问题:每个人的信息应该是不一样的,但是通过以上组件生成出来的人都是一模一样的的。

 ReactDOM.render(<Person/>,document.getElementById('app1'))
 ReactDOM.render(<Person/>,document.getElementById('app2'))
 ReactDOM.render(<Person/>,document.getElementById('app3'))

页面内容:

  • name:Tom

  • sex:man

  • age:20

  • name:Tom

  • sex:man

  • age:20

  • name:Tom

  • sex:man

  • age:20

我们渲染了三个人的组件信息,发现都是一模一样的,且不能改变。这是非常不合理的,所以我们要使用一个新的属性props来实现我们需要的功能。


props_79">使用props属性改造案例

   我们参考官网,使用props改造以上案例。

class Person extends React.Component {
      
      render () {
        const {name,age,sex} = this.props
        return (
          <ul>
            <li>name:{name}</li>
            <li>sex:{sex}</li>
            <li>age:{age}</li>
          </ul>
        )
      }
    }
    // 2、将虚拟DOM渲染到页面,标签必须闭合
    ReactDOM.render(<Person name="genius" age="25" sex="男"/>,document.getElementById('app'))

页面内容

  • name:genius
  • sex:男
  • age:25

以上就是我们使用props改造的案例,我们发现它和HTML标签属性的使用方式差不多,你传什么属性react就把你的属性放在props对象身上,组件内部使用的时候,就从props身上拿出来使用。

这个时候我们就可以通过多个组件实例生成不同的人的信息了

 ReactDOM.render(<Person name="Tom" age="20" sex="男"/>,document.getElementById('app1'))
 ReactDOM.render(<Person name="李琴" age="25" sex="女"/>,document.getElementById('app2'))
 ReactDOM.render(<Person name="张三" age="25" sex="男"/>,document.getElementById('app3'))

以上我们了解了props的基础使用方式。


批量传递标签属性

   以上案例我们使用的属性很少,但是在真实项目中,我们使用网络请求从数据库拿到的信息非常多,难道我们也要一个一个的往组件身上加属性吗?react为我们提供了一个便捷的方式。

const p = {name:"Tom",sex:"man",age: 20}

ReactDOM.render(<Person {...p} />,document.getElementById('app'))

我们可以使用扩展运算符将属性批量的添加到组件里面去,效果是一样的。

注意:需要我们注意的是你传入的属性名是什么,在组件内部使用的时候必须一致,否则是个空值。


props_137">控制props的数据类型与默认值

   现在我们加一个需求,让组件信息里面的年龄在真实年龄的基础上+1,并展示。

class Person extends React.Component {
      
      render () {
        const {name,age,sex} = this.props
        return (
          <ul>
            <li>name:{name}</li>
            <li>sex:{sex}</li>
            <li>age:{age + 1}</li>
          </ul>
        )
      }
    }
// 2、将虚拟DOM渲染到页面,标签必须闭合
ReactDOM.render(<Person name="Tom" age="25" sex="男"/>,document.getElementById('app'))

页面展示:

  • name:Tom
  • sex:男
  • age:251

我们可以看到,我们的年龄变成了251,说明该运算进行的是【字符串连接】而不是【数值运算】。说明是我们的props属性类型出了问题,我们修改一下

ReactDOM.render(<Person name="Tom" age={25} sex="男"/>,document.getElementById('app'))

我们在修改代码以后,在看结果:

  • name:Tom
  • sex:男
  • age:26

修改了标签属性的数据类型后,年龄运算进行了【数值运算】。

但是这是我们知道该组件该传入什么数据类型的情况下进行的修改,但是别人不一定知道,有什么方法提示别人传入标签属性的数据类型呢?如果不传或者漏传一个属性,其默认值该如何设置呢?


步骤1:引入prop-types 用于组件的属性类型限制

 <!-- 引入prop-types 用于组件的属性类型限制 -->
 <script src="../JS/prop-types.js"></script>

引入了该脚本后,全局多了一个叫PropTypes的对象。

步骤2:给组件的标签属性设置类型限制

 // 设置属性类型以及是否必填
Person.propTypes = {
    name: PropTypes.string.isRequired, // 限制字符串,且必传
    sex: PropTypes.string, // 限制字符串
    age: PropTypes.number, // 限制数值
    speak: PropTypes.func // 限制函数
}

通过给组件类一个特定的属性propTypes来规范标签属性的数据类型限制。

步骤3:给组件的标签属性设置默认值

// 对属性值设置默认值
Person.defaultProps = {
    sex: '不男不女',
    age: 18
}

通过给组件类一个特定的属性defaultProps来设置标签属性的默认值,当没有传入该属性值时显示其默认值。

步骤4:测试是否有效

const p = {name:9527, sex:'man', age:20}
ReactDOM.render(<Person {...p}  />,document.getElementById('app'))

以上配置会报错:

 Failed prop type: Invalid prop `name` of type `number` supplied to `Person`, expected `string`.

错误说明:提供给“Person”的“number”类型的无效道具“name”,预期为“string”。

说明我们的类型限制生效了。当我们将name属性的值改回字符串形式,错误就会消失。

在测试一下默认值是否生效:

const p = {name:'Tom'}
ReactDOM.render(<Person {...p}  />,document.getElementById('app'))

此时我们不传sexage属性,看看页面内容。

  • name:Tom
  • sex:不男不女
  • age:19

说明sex属性展示的是默认值,age为什么是19呢?因为我们在内部+1了,所以age也是使用的默认值18

到此说明我们的类型限制和默认值设置都已经生效了。


props_262">简化props的写法

   之前我们使用propTypesdefaultProps 都是通过类调用的,说明这是类的静态属性,我们以此修改代码:

 class Person extends React.Component {

     // 设置属性类型以及是否必填
    static propTypes = {
      name: PropTypes.string.isRequired, // 限制字符串,且必传
      sex: PropTypes.string, // 限制字符串,默认值:不男不女
      age: PropTypes.number, // 限制数值,默认值:18
      speak: PropTypes.func // 限制函数
    }

    // 对属性值设置默认值
    static defaultProps = {
      sex: '不男不女',
      age: 18
    }
      
      render () {
        console.log(this)
        const {name,age,sex} = this.props
        return (
          <ul>
            <li>name:{name}</li>
            <li>sex:{sex}</li>
            <li>age:{age + 1}</li>
          </ul>
        )
      }
 }

   
// 2、将虚拟DOM渲染到页面,标签必须闭合
ReactDOM.render(<Person name="Tom"  />,document.getElementById('app'))

props_303">扩展构造函数与props

在react官网中对构造函数是这样描述的:

如果不初始化 state 或不进行方法绑定,则不需要为 React 组件实现构造函数。

在 React 组件挂载之前,会调用它的构造函数。在为 React.Component 子类实现构造函数时,应在其他语句之前前调用 super(props)。否则,this.props 在构造函数中可能会出现未定义的 bug。

通常,在 React 中,构造函数仅用于以下两种情况:

  • 通过给 this.state 赋值对象来初始化内部 state。
  • 为事件处理函数绑定实例

constructor() 函数中不要调用 setState() 方法。如果你的组件需要使用内部 state,请直接在构造函数中为 this.state 赋值初始 state

constructor(props) {
super(props);
// 不要在这里调用 this.setState()
this.state = { counter: 0 };
this.handleClick = this.handleClick.bind(this);
}

大概意思是如果你创建了构造函数,如果不调用super(props)语句,在构造函数中的this.props出出现未定义的bug。

我们尝试一下:

constructor(props){
    super()
    console.log('constructor',this.props)
}

这里我们打印的this.props的结果是:undefined


将类式组件改造为函数式组件

   在函数组件中,props是作为函数的参数传递的。所以我们的函数式可以使用props

function Person (props) {
     const {name,age,sex} = props
     return (
          <ul>
            <li>name:{name}</li>
            <li>sex:{sex}</li>
            <li>age:{age + 1}</li>
          </ul>
        );
    }

    // 设置属性类型以及是否必填
    Person.propTypes = {
      name: PropTypes.string.isRequired, // 限制字符串,且必传
      sex: PropTypes.string, // 限制字符串,默认值:不男不女
      age: PropTypes.number, // 限制数值,默认值:18
      speak: PropTypes.func // 限制函数
    }

    // 对属性值设置默认值
    Person.defaultProps = {
      sex: '不男不女',
      age: 18
    }
    // 2、将虚拟DOM渲染到页面,标签必须闭合
    ReactDOM.render(<Person name="Tom"  />,document.getElementById('app'))

将其改为函数式组件,运行控制台不报错,且数据类型和默认值生效。


总结Props

  • 1、props是一种用于组件之间传递数据的机制。它是一个对象,包含了组件的属性和值。
  • 2、可以通过扩展运算符({…p})来批量传入标签属性
  • 3、可以通过propTypes属性来限制标签属性的数据类型
  • 4、可以通过defaultProps属性来设置标签属性的默认值
  • 5、标签属性不能修改,只能读取
  • 6、函数式组件也能使用props

http://www.niftyadmin.cn/n/191981.html

相关文章

vue3中tsx语法一些了解

首先直接创建tsx文件 引入函数 import { defineComponent, ref } from vue 直接使用组件函数的写法 export default defineComponent({//context内有参数emit,slot,arrts,expose //解构写法setup( props,{emit,slot,arrts,expose}){}setup( props,context) {//定义函数和响应…

机器学习12(Scikit-Learn)

目录简介Scikit-Learn概念LinearRegression实用函数超参数参数求解方法常用功能数据集读取标准化与归一化标准化归一化逻辑回归评估器机器学习流简介 前面我们通过 算法理论手动实现 的方式&#xff0c;深入了解了机器学习的基本原理这种方式不仅深化了对基础原理的理解&#…

基于ZYNQ 的多轴运动控制平台关键技术研发-总体架构设计(一)

基于多轴运动控制平台的实时通信和同步控制需求&#xff0c;采用 Xilinx Zynq 7020 SoC 作为核心处理器&#xff0c;设计了双核 SoC 多轴运动控制平台的总体架构。结合多轴运动控 制系统与接口特征&#xff0c;完成了 SoC 运动控制平台的硬件设计&#xff0c;主要包括 SoC 最小…

Python进阶语法

1.1 Python进阶语法 1.1.1 交换变量 一行代码快速交换两个变量&#xff0c;无需创建临时变量。 from icecream import ica 2 b 4 a, b b, a ic(a, b)ic| a: 4, b: 2 1.1.2 链式比较 from icecream import ica 97 if 90 < a < 100:ic(a)ic| a: 97 1.1.3 初始化列表…

基于Spring、SpringMVC、MyBatis的汽车租赁系统设计

文章目录 项目介绍主要功能截图:前台首页汽车信息列表汽车租赁留言反馈个人信息管理后台汽车类型管理汽车信息管理租赁信息管理用户管理续租信息管理归还信息管理保险信息管理违章登记管理部分代码展示设计总结项目获取方式🍅 作者主页:Java韩立 🍅 简介:Java领域优质创…

为什么我们mysql从双主切换到了单主?

文章目录 MySQL 双主 + Keepalived 的模式问题二、双主降为主从主从模式三、改为主从的简单方式四、总结MySQL 双主 + Keepalived 的模式问题 因为两个 MySQL 节点都可以写入,极其容易造成主键重复,进而导致主从同步失败。同步失败后,Slave_SQL_Thread 线程就停了,除非解决…

基于springboot实现校友社交交流平台系统演示【附项目源码+论文说明】

基于springboot实现校友社交交流平台系统演示开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven包…

前端开发——Javascript的定义函数、事件处理、Math对象、Date对象

当你去的地方多了&#xff0c;你就会摆脱地域的偏见 当你看的书籍多了&#xff0c;你就会走出时代的局限 ——Lungcen 目录 JS函数 JS 定义函数 参数的默认值 JS事件&#xff08;event&#xff09;处理 事件绑定 事件示例 Math&#xff08;数学&#xff09;对象 有关随机数的知…