当前位置: 首页 > news >正文

深度讲解React Props

一、props的介绍

当React遇到的元素是用户自定义的组件,它会将JSX属性作为单个对象传递给该组件,这个对象称之为“props”。

函数声明的组件,会接受一个props形参,获取属性传递的参数

function ComponentA(props) { return <div>我是组件B:{props.value}</div>
}

如果函数组件需要props功能,一定不能缺少该形参
类的声明,在react组建中,使用constructor 获取Component类的props属性当组件继承了父类props后,就可以通过this.props属性名进行属性传值

class ComponentB extends React.Component {constructor(props) {super(props);}render() {return <div>我是组件B {this.props.name}</div>}
}

类的继承子类必须在constructor方法中调用super方法,否则新建实例时会报错

这是因为子类自己的this对象,必须先通过父类的构造函数完成塑造,得到与父类同样的实例属性和方法,然后再对其进行加工,加上子类自己的实例属性和方法。如果不调用super方法,子类就得不到this对象。

注意: props可以传递任何数据类型,并且props是只读的(单项数据流),所有的React组件必须像纯函数那样使用它们的props。

二、批量传递props

情景: 有时我们要传递的参数不止一个的话,那如果是每个都写,10个也许你能接受,那100个,1000个呢。那你的代码简直神了。

既然如此,我们就借用ES6中的展开运算符(…),就是三个点这玩意。

我们直接先定义好传递的参数,然后再传递。

class Person extends React.Component {render() {console.log(this);  // Person 实例对象const { name, age, sex } = this.props;return (<ul><li>姓名: {name}</li><li>性别: {sex}</li><li>年龄: {age}</li></ul>)}
}// 单个传递
ReactDOM.render(<Person name="Tom" age="18" sex="woman" />, document.getElementById('test'))
ReactDOM.render(<Person name="Jack" age="19" sex="man" />, document.getElementById('test1'))// 批量传递
const p = { name: '老王', age: 30, sex: 'man' }
ReactDOM.render(<Person {...p}/>, document.getElementById('test2'))

三、props的验证

随着应用日渐庞大,通常你希望每个 props 都有指定的值类型,并可以通过类型检查捕获大量错误,便捷开发减少异常维护时间,要检查组件的props属性,你需要配置组件特殊的静态 propTypes 属性并配合prop-types 三方库实现prop验证。(prop-types 在react脚手架中自带无需下载)

在16版本之前的方式

ComponentA.propTypes = {name: React.PropTypes.string.isRequired, // 限制name必传,且为字符串
}

16版本之后,单独作为一个库使用

  1. 写法一: 给类组件的class设置属性 propTypes
import React, {Component} from 'react'
import PropTypes from 'prop-types'class ComponentA extends Component {render() {// 因为 jsx 元素本质上是 React.createElement() 隐式调用的// 所以如果你的js文件中包含jsx元素就必须import React 支持让jsx元素隐式调用否则编译器会报错//  'React' must be in scope when using JSXreturn (<div><p>name: {this.props.name}</p><p>age: {this.props.age}</p></div>)}
}ComponentA.propTypes = {name: PropTypes.string,age: PropTypes.number
}export default ComponentA
  1. 使用class 静态属性语法(static) 设置 propTypes,类的自身添加的属性。
import React, {Component} from 'react'
import PropTypes from 'prop-types'class ComponentA extends Component {static propTypes = {name: PropTypes.string,age: PropTypes.number}render() {// 因为 jsx 元素本质上是 React.createElement() 隐式调用的// 所以如果你的js文件中包含jsx元素就必须import React 支持让jsx元素隐式调用否则编译器会报错//  'React' must be in scope when using JSXreturn (<div><p>name: {this.props.name}</p><p>age: {this.props.age}</p></div>)}
}export default ComponentA
  1. 默认属性值,当某个属性没有传递的时候,就使用你定义的值
// 指定默认标签属性值 
Person.defaultProps = { sex: '男', age: 17 
}
  1. 函数组件支持通过给构造函数设置属性,进行组件props验证
import React, {Component} from 'react'
import PropTypes from 'prop-types'class ComponentA extends Component {static propTypes = {name: PropTypes.string,age: PropTypes.number}render() {// 因为 jsx 元素本质上是 React.createElement() 隐式调用的// 所以如果你的js文件中包含jsx元素就必须import React 支持让jsx元素隐式调用否则编译器会报错//  'React' must be in scope when using JSXreturn (<div><p>name: {this.props.name}</p><p>age: {this.props.age}</p></div>)}
}export default ComponentA

四、类式组件中的构造器与props

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

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

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

  • 通过给 this.state 赋值对象来初始化内部 state。
  • 为事件处理函数绑定实例 (bind改变this指向)
// state的基本使用constructor(props) {super(props);// 初始化状态this.state = {isHot: true,wind: '大风'}// bind: 做了两件事情 ---- 生成新的函数并且改变this为Weather的实例对象// this.changeWeather是原型上的方法,通过bind改变this之后生成新的方法放在了实例自身上,导致了实例中也有changeWeather这个方法,这样就能进行调用了this.changeWeather = this.changeWeather.bind(this);  
}

传不传props之间的区别

class Person extends React.Component {// 1、传入props并且也传给了superconstructor(props) {// console.log(props)super(props);console.log(this.props);  // 组件所传入的所有props  如:{name: "Tom", sex: "男", age: 17, speak: ƒ}}// 2、传入props但不传给superconstructor(props) {// console.log(props)super();console.log(this.props); // undefinedconsole.log(props); // 组件所传入的所有props  如:{name: "Tom", sex: "男", age: 17, speak: ƒ}}// 3、都不传constructor() {// console.log(props)super();console.log(this.props); // undefined}}

参考 前端进阶面试题详细解答

总结:

构造器是否接收props,是否传递给super, 取决于:是否希望在构造器中通过this访问props

五、三方库prop-types的使用

基础类型验证

PropTypesDemo.propTypes = {propsArray: PropTypes.array, // 数组propsObject: PropTypes.object, // 对象propsString: PropTypes.string, //字符串propsNumber: PropTypes.number, // 数字propsBool: PropTypes.bool, // 布尔值propsSymbol: PropTypes.symbol, // 私有数据类型propsFunc: PropTypes.func, // 函数//  节点数据类型(任何可以渲染的数据类型)propsNode: PropTypes.node,//  react元素(jsx)propsElement: PropTypes.element,
}    

React中 对象 bool symbol func都是不能直接渲染在页面上的这些数据类型都不属于node类型

必传属性修饰符isRequired

prop-types所有类型后丢可以跟isRequired修饰符代表该属性是必传属性

PropTypesDemo.propTypes = {propsArray: PropTypes.array.isRequired, // 必传 Array 类型propsElement: PropTypes.element.isRequired // 必传 element 类型propsAny: PropTypes.any.isRequired // 必传 任意数据类型
}

prop-types 还提供了一个any数据类型表示任意数据类型,该类型主要是配合isRequired修饰符,表示当前属性不能为空

复杂类型验证

PropTypesDemo.propTypes = {// 数据为指定构造函数函数的实例propsCurrentProto: PropTypes.instanceOf(Dog),// 属性值为指定的值的其中之一propsOneOf: PropTypes.oneOf(['男', '女']),// 属性的数据类型为指定类型的其中之一propsOneOfType: PropTypes.oneOfType([PropTypes.array,PropTypes.object,PropTypes.instanceOf(RegExp),PropTypes.oneOf(['男', '女'])]),// 指定每一项数据类型的数组propsStringArray: PropTypes.arrayOf(PropTypes.string),// 指定每一项键值对value数据类型的对象propsDateObj: PropTypes.objectOf(PropTypes.instanceOf(Date)),// 指定key和value数据类型的对象propsCurrentObject: PropTypes.shape({name: PropTypes.string, // 这个属性可以为缺省值age: PropTypes.number.isRequired // 该属性在当前对象中必须存在})}

除了 instanceOf,oneOf以外其他几个验证规则可以互相嵌套, isRequired修饰符依然可以在上述验证规则中使用 自定义验证规则

在React 组件的propTypes属性中可以给指定的属性,设置一个验证函数实现一些自定义验证规则。自定义验证函数一般情况下接收三个参数:propspropNamecomponentName

  • props :当前组件接收到的属性传参的对象集合

  • propName :使用当前自定义规则的属性名

  • componentName :当前组件名

当接收props的属性值不能通过验证规则时只需要向函数外部返回一个Error实例对象就好了。

案例: 实现自定义验证规则,传入的数据必须是字符串或者数字,字符串不能包含“fxxk”敏感字符,数字必须大于等于18 小于等于 120。

ComponentC.propTypes = {propsA: function (props, propName, componentName) {let val = props[propName]if(typeof val === 'string') {if(/fxxk/.test(val)) {return  new Error(`组件:${componentName},中属性"${propName}"值为${val}包含敏感字符`)}}else if(typeof val === 'number') {if(val < 18 || val > 120 ){return  new Error(`组件:${componentName},中属性"${propName}"值为${val}不满足18-120区间`)}}else {return new Error(`组件:${componentName},中属性"${propName}" 值不是字串或数字`)}}}

定义验证规则配合arrayOf 或者 ObjectOf使用

自定义验证函数可以作为参数传递给prop-types库的arrayOf 或者 ObjectOf中对数组,对象进行遍历验证。这时该验证规则函数接收5个参数:propValuekeycomponentNamelocationpropsFullName

  • propValue :当前验证的数组或者对象自身

  • key : 遍历数组的下标或对象的key值

  • componentName :当前组件名

  • location :当前值的位置常量 “prop”

  • propsFullName :遍历出来当前项的字符串全名

例子: propsCustomArrayOf[2]propsCustomArrayOf.name

PropTypesDemo.propTypes = {//  arrayOf 或者 ObjectOf 自定义验证规则propsCustomArrayOf: PropTypes.arrayOf(function (propValue, key, componentName, location, propsFullName) {if(!/matchme/.test(propValue[key])) {return new Error(`Failed prop type: Invalid prop '${propsFullName}' supplied to ${componentName}.Validation failed.`)}}),propsCustomObjectOf: PropTypes.objectOf(function (propValue, key, componentName, location, propsFullName) {if(!/matchme/.test(propValue[key])) {return new Error(`Failed prop type: Invalid prop '${propsFullName}' supplied to ${componentName}.Validation failed.`)}}),}

六、小总结

  1. 每个组件对象都会有props(properties的简写)属性

  2. 组件标签的所有属性都保存在props

  3. 通过标签属性从组件外向组件内传递变化的数据

  4. 注意: 组件内部不要修改props数据

  5. 使用propTypes 属性并配合prop-types 三方库实现prop验证(不用另外下载,已集成在脚手架中)

相关文章:

深度讲解React Props

一、props的介绍 当React遇到的元素是用户自定义的组件&#xff0c;它会将JSX属性作为单个对象传递给该组件&#xff0c;这个对象称之为“props”。 函数声明的组件&#xff0c;会接受一个props形参&#xff0c;获取属性传递的参数 function ComponentA(props) { return <…...

WebRTC现状以及多人视频通话分析

1.WebRTC 概述WebRTC&#xff08;网页实时通信技术&#xff09;是一系列为了建立端到端文本或者随机数据的规范&#xff0c;标准&#xff0c;API和概念的统称。这些对等端通常是由两个浏览器组成&#xff0c;但是WebRTC也可以被用于在客户端和服务器之间建立通信连接&#xff0…...

【Windows】Windows下wget的安装与环境变量配置

1 wget安装 GNU Wget常用于使用命令行下载网络资源&#xff08;包括但不限于文件、网页等&#xff09;。 GNU Wget官网&#xff1a;GNU Wget GNU Wget for Windows&#xff1a;GNU Wget for Windows 安装时首先下载主安装包&#xff1a;Complete package, except sources&…...

密码学基础概念

把一段原始数据通过某种算法处理成另外一种数据&#xff08;原始数据为明文&#xff0c;处理后的数据为密文&#xff09;。明文->密文&#xff1a;称之为加密。密文->明文&#xff1a;称之为解密。 在加密过程中我们需要知道下面的这些概念&#xff1a; 1&#xff09;明文…...

科技巨头争相入局,卫星通信领域将迎来怎样的发展?

近年来&#xff0c;全球卫星通信产业进入了一个高速发展的阶段 与卫星通信相关的新技术和新应用不断出现&#xff0c;成为了媒体报道的热点&#xff0c;也引起了公众的广泛关注。 尤其是刚刚过去的2022年&#xff0c;华为和苹果公司分别发布了搭载卫星通信技术的手机&#xf…...

银行软件测试面试题目总结,希望可以帮到你

目录 一、根据题目要求写出具体LINUX操作命令 二、JMETER题目 三、根据题目要求写出具体SQL语句 总结感谢每一个认真阅读我文章的人&#xff01;&#xff01;&#xff01; 重点&#xff1a;配套学习资料和视频教学 一、根据题目要求写出具体LINUX操作命令 1、分别写出一种…...

MySQL数据定义

系列文章目录前言创建数据库删除数据库修改数据库修改表结构修改表中列修改表中约束创建表删除表前言 创建数据库 创建数据库CREATE DATABASE 数据库名 使用数据库use 数据库名; MySQL数据库如何建表 删除数据库 删除数据库语句DROP DATABASE 数据库名 这条语句会删除数据…...

跨设备文件传输工具横评

文章目录对比QQ微信SnapDropLocalSendIntelUnisonLANDropTailscaleAirDroidSendAnywhere参考文献对比 传输速度测试条件大致相同&#xff0c;文件大小约为 100 MB 工具优点缺点传输速度备注QQ支持断点续传不要求同一局域网需要安装1.81 MB/s微信方便需要安装不支持大文件传完还…...

Oracle通过SQL找出ID不连续的位置

文章目录1 前言2 SQL3 结语1 前言 工作中要求我找到 ID 不连续的地方, 然后拿这个 ID , 给数据库里面 INSERT 一条数据. 比如: ID备注… 省略连续的部分232425就是想找到这里断开的地方, 下一个可以 INSERT 的 ID 就是 2674915751157512075122… 省略连续的部分 2 SQL 假设数据…...

学习一个Java项目

你想学习一个项目&#xff0c;一行一行去看代码 效率很低&#xff0c;看了就忘了 理清学习的思路 项目分为两部分&#xff1a;业务和代码 一、如何熟悉业务 1、看项目的文档&#xff08;需求概要文档、设计文档&#xff09; 2、同事/前辈言传身教 3、自己动手使用功能 …...

《数据库系统概论》学习笔记——第三章 关系数据库标准语言SQL

教材为数据库系统概论第五版&#xff08;王珊&#xff09; 最重量级的一章。从后续的学习&#xff0c;基本所有实验&#xff0c;大作业和考试都会涉及SQL&#xff0c;SQL实际上是有很多变化的&#xff0c;书上讲的只是最基本的&#xff08;做了大作业才知道SQL能有这么多变化&a…...

linux shell 入门学习笔记17 mysql脚本开发

开发mysql监控脚本 需要了解的命令&#xff1a; ss命令展示 xiao123xiao123:~/Downloads/shscripts$ ss -tunlp Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port Process udp UNCONN 0 0 …...

产品新说 | 指标的异常检测怎么做,能更好配合业务变化(二)

前言&#xff1a;上期分享我们提到了指标异常检测实践要素中的三个方面&#xff1a;以面对业务变动为前提&#xff0c;确定业务波动是周期性还是非周期性&#xff0c;进而选对算法&#xff1b;通过确认业务的常规指标&#xff0c;确定异常方向进行监测&#xff08;上基带 / 下基…...

华为OD机试题,用 Java 解【最短耗时】问题

最近更新的博客 华为OD机试题,用 Java 解【停车场车辆统计】问题华为OD机试题,用 Java 解【字符串变换最小字符串】问题华为OD机试题,用 Java 解【计算最大乘积】问题华为OD机试题,用 Java 解【DNA 序列】问题华为OD机试 - 组成最大数(Java) | 机试题算法思路 【2023】使…...

mysql数据库常见面试题

慢查询排查优化 排查 slow_query_log设置为on&#xff0c;就会记录慢查询sql&#xff1b;long_query_time可以设置慢查询sql的阈值时间&#xff1b;slow_query_log_file表示记录慢查询sql的日志路径。即我们可以通过打开记录慢查询的开关&#xff0c;设置慢查询的时间阈值&…...

【Android源码面试宝典】MMKV从使用到原理分析(一)

去年,我们写过一篇文章,对于android原生提供的key-value存储API SharePreference,进行了从使用到原理的深入分析,同时对其中存在的ANR问题、存取慢等问题,进行了深入的探索、总结。但是之前的文章,我们仅仅指出了问题,没有给大家提供解决方案,也就是说,SharePreferenc…...

你真的懂动态库吗?一文详解动态库的方方面

这里写目录标题创建动态库创建静态库动态库与静态库的区别动态链接与静态链接的区别动态库的加载过程dll的创建以及应用程序隐式链接到dll的过程dll的创建以及应用程序显示链接到dll的过程动态库的二进制兼容性创建动态库 1.【新建】-》【项目】-》【动态链接库】 新建的动态…...

I.MX6ULL内核开发12:使用设备树插件实现RGB灯驱动

目录 一、引言 二、设备树插件格式 三、实验说明 四、实验准备 4.1 通过内核工具编译设备树插件 五、实验效果 5.1 uboot加载 5.2 加载RGB驱动 一、引言 Linux4.4以后引入了动态设备树&#xff08;Dynamic DevicesTree&#xff09;&#xff0c;这里翻译位“设备树插件…...

大家一起来找茬,新手第一次layout到底能挑出多少毛病?

有一个新手工程师在论坛上发了一篇帖子&#xff0c;把自己的处女PCB布线图贴出来。 如果不看其他网友的评论&#xff0c;你能看出多少问题呢&#xff1f;可以在留言区和我们互动哦~ 帖子里他还提出了自己的小见解&#xff1a;问一下&#xff0c;我觉得自动布线挺好用的啊&#…...

Java集合概述(Collection集合)

目录集合一、集合与数组二、集合类体系结构三、泛型(约定集合存储数据类型)四、Collection集合常用API五、Collection集合的遍历方式5.1 迭代器遍历5.2 增强for循环(for each):5.3 lambda表达式六、Collection集合存储自定义类型的对象七、常见数据结构集合 一、集合与数组 数…...

运动无线蓝牙耳机哪款好、运动无线蓝牙耳机推荐

作为 运动爱好者&#xff0c;每天早晨醒来后的第一件事就去家门口的湿地公园跑上一圈。各种运动装备都齐了&#xff0c;不过在耳机选择上还真的犯难&#xff0c;打着“运动耳机”旗号的产品也是种类繁多&#xff0c;那么到底什么样的无线耳机更适合运动呢&#xff1f;于是我花时…...

解决AAC音频编码时间戳的计算问题

1.主题音频是流式数据&#xff0c;并不像视频一样有P帧和B帧的概念。就像砌墙一样&#xff0c;咔咔往上摞就行了。一般来说&#xff0c;AAC编码中生成文件这一步&#xff0c;如果使用的是OutputStream流写入文件的话&#xff0c;就完全不需要计算时间。但在音视频同步或者使用A…...

Android 9.0 添加自定义开机广播

1.概述 在9.0的系统rom定制化开发中,由于系统开机广播接收受限,普通app接收不到这个广播,如果接收这个广播很多应用 感觉要好久收到这个广播, 所以需要自定义开机广播来使用自定义广播开启某些应用,实现自己的功能,接下来就需要分析下开机广播的流程,然后增加自定义广播…...

第四阶段10-添加类别,类别列表mapper层,service层,controller层

63. 添加类别–Mapper层 插入类别数据的功能此前已经完成&#xff01; 64. 添加类别–Service层 在项目的根包下创建pojo.dto.CategoryAddNewDTO类&#xff1a; Data public class CategoryAddNewDTO implements Serializable {/*** 类别名称*/private String name;/*** 父…...

linux内核启动分析(一)

文章目录1.HEAD1.preserve_boot_args1.1 __inval_dcache_area2.el2_setup3. set_cpu_boot_mode_flag4. __create_page_tables4.1map_memory5. __cpu_setup6. __primary_switch6.1 __enable_mmu6.2 __primary_switched最近工作中经常使用飞腾E2000的开发版&#xff0c;也遇到一些…...

wireshark常见使用操作讲解以及几个故障解决案例分享

&#xff08;1&#xff09;网卡选择 对于电脑本身有多个网卡的时候&#xff0c;选择网卡就成为了一个困惑的地方&#xff0c;其实这里很简单&#xff0c;只要把鼠标放在对应的网卡上面就可以看到地址等信息&#xff0c;就容易判断出来了。 &#xff08;2&#xff09;过滤器 直…...

利用逻辑分析仪解析串口通讯数据

利用逻辑分析仪解析串口通讯数据&#x1f527;采用的是市面上最为广泛使用的USB逻辑分析仪: &#x1f4da;资料下载&#xff1a; 链接: https://pan.baidu.com/s/1c9lwWDbtJxaJED-kzSbiJg 提取码: 5vnr&#x1f528;测试工具为&#xff1a;Logic 2.4.6&#xff0c;也可以使用Pu…...

新整理的前端面试题

pinia和vuex的区别&#xff08;1&#xff09;pinia它没有mutation,他只有state&#xff0c;getters&#xff0c;action【同步、异步】使用他来修改state数据&#xff08;2&#xff09;pinia他默认也是存入内存中&#xff0c;如果需要使用本地存储&#xff0c;在配置上比vuex麻烦…...

数据仓库-数仓分层

层级 全拼 职责划分 ODS(源数据层) Operational DataStore ODS层存储最原始的数据&#xff0c; 对数据不做任何加工处理&#xff1b; 源数据主要来自业务数据库和日志&#xff0c;这些数据是用户操作业务系统产生&#xff0c;所以叫操作型数据(Operational Data) 。 DWD(…...

【Linux】Linux根文件系统扩容

场景&#xff1a;根文件系统需要至少100GB的剩余空间&#xff0c;但是目前就剩余91GB。因此&#xff0c;我们需要对根文件系统进行扩容。# df -h 文件系统 容量 已用 可用 已用% 挂载点 devtmpfs 3.9G 0 3.9G 0% /dev tmpfs …...

扬州政府门户网站建设的调查报告/百度指数关键词

随着液晶拼接大屏幕显示系统设备的应用越来越广阔&#xff0c;很多人似乎对矩阵与液晶拼接屏的连接方法还是一知半解&#xff0c;下面耐诺科技为您详细的介绍一下矩阵与液晶拼接屏的连接方法3*31. 周边设备&#xff1a;一套完整的液晶拼接大屏幕显示系统还需要有各类线材、每一…...

中英企业网站源码/网上seo研究

在linux的系统维护中&#xff0c;可能需要经常查看cpu使用率&#xff0c;分析系统整体的运行情况。而监控CPU的性能一般包括以下3点&#xff1a;运行队列、CPU使用率和上下文切换。 对于每一个CPU来说运行队列最好不要超过3&#xff0c;例如&#xff0c;如果是双核CPU就不要超…...

做视频网站适合用什么服务器/松原头条新闻今日新闻最新

我们在写程序的时候经常会打一些日志来帮助我们查找问题&#xff0c;这次学习一下logging模块&#xff0c;在python里面如何操作日志。介绍一下logging模块&#xff0c;logging模块就是python里面用来操作日志的模块&#xff0c;logging模块中主要有4个类&#xff0c;分别负责不…...

农产品电商网站建设/网站优化seo怎么做

简单的爬虫 from urllib.request import urlopenurl"http://www.baidu.com" responseurlopen(url) #发送请求&#xff0c;返回响应 inforesponse.read()#读取内容print(info.decode())#打印内容 print(response.getcode())#打印状态码 print(真是的url&#xff1a;r…...

网站建设教程浩森宇特/视频app推广

基于Android 11&#xff1a;三星OneUI 3.0详细升级计划公布2020-12-02 22:06:1414点赞18收藏47评论本周&#xff0c;三星方面公布了基于Android 11的OneUI 3.0具体升级安排&#xff0c;其最早出现在埃及地区手机用户的三星会员APP中。2020年12月&#xff1a;Galaxy S20 Ultra、…...

wordpress 安卓接口/全球搜索引擎市场份额

1&#xff0c;在扩展节点M时&#xff0c;计算了其后继节点N的F值&#xff0c;发现N节点已经在open链表中&#xff0c;并且新的F值小于老的F值&#xff0c;但是此时不进行F值的更新&#xff0c;那么修改过的算法正确吗&#xff1f;很简单不正确的&#xff0c;看下面这个图 图…...