安装React开发调试工具(React Developer Tools)
安装步骤(需要科学上网):
安装成功:
在通过React开发并处于本地开发的页面上图标会显示为红色,说明安装成功:
通过React开发并处于线上版本的网页,图标会显示为黑色:
非React开发的页面上图标会显示为灰色:
React Developer Tools 的好处
- 方便进行 组件结构 的查询、
- 在组件传值调试时不需要反复通过 console.log 来打印信息,直接看 开发者工具 右侧 state 中是否有相关信息即可。
使用React Developer Tools
进入原始页面,打开 开发者工具 ,可以看到新增的 Component :
在输入框内依次输入a b,可以看到右方 state 实时产生变化:
可以很方便的进行 组件结构 查询:
PropTypes与DefaultProps的应用
PropTypes 强校验
子组件在接受父组件传过来的值(即 属性 )时进行强校验。他可以要求父组件给子组件传的值是什么类型的。如若不是也并不会报错,只会在 开发者工具 中给出警告。
使用步骤
- 脚手架工具中已经有 prop-types 的包,所以我们可以直接在 子组件 中顶部引入 PropTypes :
1
import PropTypes from 'prop-types';
- 在 子组件
export default
顶上使用 propTypes (注意是小写)限制父组件传过来的值的类型(更多值的类型可以看下面”PropTypes不同的验证函数“):1
2
3
4
5
6
7// 使用propTypes限制父组件传过来的值的类型
TodoItem.propTypes = {
// 注意PropTypes大小写,上面必须小写,下面是import中自定义的名字
content: PropTypes.string,
deleteItem: PropTypes.func,
index: PropTypes.number
} - 如果将 index 的 PropTypes要求 改为 string ,则一旦提交输入内容后就会给出 警告 ,告诉我们子组件接收 index 时希望得到的是 string 类型的而不是 number :
isRequired
强制传值
总结:
- 当父组件没有向子组件传某个值时,某个值对应的propTypes是不生效的。
- 使用
isRequired
可以强制要求父组件向子组件传递某个值,如果父组件并未传值就会报出 警告 。
例子1:
子组件上增加 test (实际上父组件并未传 test ):
对子组件上 test 进行强校验:
然而到页面上输入时并未报出警告,也就是说test: PropTypes.string
是没有生效的。
例子2:
在 propTypes 中使用isRequired
强制要求父组件向子组件传递test值:
父组件并未传值,报出 警告:
DefaultProps 设置默认值
当父组件没有向子组件传递某个值,而子组件使用了该值时,可以在子组件中设置DefaultProps来规定该值的默认值。
注意:上面强校验时引入了PropTypes是因为需要使用PropTypes内的类型(string、func、number等),而DefaultProps不需要另外引入别的包。
有时候你使用isRequired
强制要求父组件传过来的值实际上没办法传,这时候就需要用到默认值来解决报错问题,结合上面的例子,我们在子组件中给test一个默认值:
官网深入学习
- 打开英文官网https://reactjs.org/。(中文官网较为滞后,推荐英文官网)
- Docs(文档)=> ADVANCED GUIDES(高级指南)=> typechecking-with-proptypes
PropTypes
- 直接拉到中间看 PropTypes使用方法的 demo:
- 再往下看可以看到 PropTypes 可以使用的各种值:
- 还可以 使用instanceOf来判断接收的值是不是Message的一个实例 等,PropTypes可以做非常丰富的代码检测:
- 假设我们希望例子中的content可以是number或者string类型,我们可以使用文档中给出的**
oneOfType
来完成“或者”的语法**:1
2
3
4
5// content 可以是number或者string类型
content: PropTypes.oneOfType([
PropTypes.number,
PropTypes.string
]),
PropTypes不同的验证函数
1 | import PropTypes from 'prop-types'; |
defaultProps
defaultProps 使用方法的 demo:
1 | class Greeting extends React.Component { |
props,state与render函数的关系
之所以state中的数据一变页面就会自动发生变化是因为页面是通过render函数渲染出来的,而每当组件的state或者props发生改变时,render函数就会重新执行。
(props发生改变,归根到底还是父组件的state发生了变化,所以我们也可以理解为state或者props发生改变时父子组件的render函数都会重新执行)
当父组件的render函数被运行时,它的子组件的render都将被重新运行一次。
state与render函数的关系:
每当组件的state内数据发生改变时,render函数就会重新执行。可以看TodoList.js
来帮助理解。
props与render函数的关系:
每当组件的props内的数据发生改变时,render函数就会重新执行。
总结:当父组件的render函数被运行时,它的子组件的render都将被重新运行一次。
例子
- 在父组件中引入子组件Test:
import Test from "./Test"
- 在父组件中将子组件Test放在无序列表下方位置并将state中的inputValue传过去,**每当父组件的render函数被运行时就会打印”render”**:
- 新建一个子组件
Test.js
,**每当子组件的render函数被运行时就会打印”Test render”**并在页面上显示父组件传过来的content(即state中的inputValue值):1
2
3
4
5
6
7
8
9
10
11
12import React, { Component } from 'react'//imrc
class Test extends Component {
render() {
console.log("Test render");
return (
<div>{this.props.content}</div>
)
}
}
export default Test;
结果:
解释:
- 最初的时候父组件需要渲染,子组件也需要渲染,所以 开发者工具 中显示了“render”和“Test render”。
- 输入1后,
inputValue
发生改变,父组件的state发生改变,所以父组件render函数重新运行,多打出来一行“render”。 - 输入1后**
inputValue
一变content
就会变(因为父组件传值<Test content={this.state.inputValue} />
),content
一变props
就变了(因为子组件中<div>{this.props.content}</div>
),props
发生改变时,render
函数就会重新执行,所以显示“Test render”**。