1. 组件通讯-概念
了解组件通讯的意义
大致步骤:
- 知道组件的特点
- 知道组件通讯意义
具体内容:
- 组件的特点
- 组件是
独立且封闭
的单元,默认情况下,只能使用组件自己的数据 - 在组件化过程中,通常会将一个完整的功能拆分成多个组件,以更好的完成整个应用的功能
- 组件是
- 知道组件通讯意义
- 而在这个过程中,多个组件之间不可避免的要
共享
某些数据 - 为了实现这些功能,就需要打破组件的独立封闭性,让其与外界沟通
- 这个过程就是组件通讯
- 而在这个过程中,多个组件之间不可避免的要
总结:
- 组件状态是独立的,组件化之后涉及状态同步,需要进行组件通讯
2. 组件通讯-props 基本使用
能够通过 props 传递数据和接收数据
大致步骤:
- 传递数据和接收数据的过程
- 函数组件使用 props
- 类组件使用 props
具体内容:
① 传递数据和接收数据的过程
- 使用组件的时候通过属性绑定数据,在组件内部通过 props 获取即可。
② 函数组件使用 props
// 使用组件
<Hello name="jack" age="20" />
// 定义组件 props包含{name:'jack',age:'20'}
function Hello(props) {return <div>接收到数据:{props.name}</div>;
}
③ 类组件使用 props
// 使用组件
<Hello name="jack" age="20" />
// 定义组件 props包含{name:'jack',age:'20'}
class Hello extends Component {render() {return <div>接收到的数据:{this.props.age}</div>;}
}
总结:
- props 是实现组件通讯的关键,它通过使用组件绑定属性,组件内部使用 props 来传值。
3. 组件通讯-props 注意事项
知道 props 是单项数据流只读,但是可以传递任意数据。
大致步骤:
- 知道什么是单向数据流
- 知道 props 可以传递什么数据
具体内容:
- 知道什么是
单向数据流
?- 单向数据流,是从上到下的,
自顶而下
的,数据流。 - 好比:河流,瀑布,只能从上往下流动,上游污染下游受影响,但是下游不能影响上游。
- 父组件传递数据给子组件,父组件更新数据子组件自动接收更新后数据,当是子组件是不能修改数据的。
- 单向数据流,是从上到下的,
- props 可以传递什么数据?
任意
- 字符串
- 数字
- 布尔
- 数组
- 对象
- 函数
- JSX (插槽)
总结:
- props 传递数据是单向的,可以传递任意格式的数据。
4. 组件通讯-父传子方式
通过 props 将父组件的数据传递给子组件
大致步骤:
- 父组件提供要传递的 state 数据
- 给子组件标签添加属性,值为 state 中的数据
- 子组件中通过 props 接收父组件中传递的数据
具体代码:
① 父组件提供要传递的 state 数据
class Parent extends React.Component {state = {money: 10000,};render() {return (<div><h1>父组件:{this.state.money}</h1></div>);}
}
② 给子组件标签添加属性,值为 state 中的数据
class Parent extends React.Component {state = {money: 10000}render() {return (<div><h1>父组件:{this.state.money}</h1>
+ <Child money={this.state.money} /></div>)}
}
③ 子组件中通过 props 接收父组件中传递的数据
function Child(props) {return (<div><h3>子组件:{props.money}</h3></div>);
}
总结:
- 父组件声明
state
,在子组件标签通过属性绑定
,在子组件中通过props
使用。
5. 组件通讯-子传父方式
通过 props 将子组件的数据传递给父组件
大致步骤:
- 父组件提供回调函数,通过 props 传递给子组件
- 子组件调用 props 中的回调函数,函数可传参
- 父组件函数的参数就是子组件传递的数据
具体代码:
① 父组件
class Parent extends React.Component {state = {money: 10000,};// 回调函数buyPhone = (price) => {this.setState({money: this.state.money - price,});};render() {const { money } = this.state;return (<div><h1>父组件:{money}</h1><Child money={money} buyPhone={this.buyPhone} /></div>);}
}
② 子组件
const Child = (props) => {const handleClick = () => {// 子组件调用父组件传递过来的回调函数props.buyPhone(5000);};return (<div><h3>子组件:{props.money}</h3><button onClick={handleClick}>买手机</button></div>);
};
总结:
- 子组件如何传递数据给父组件?
- 触发父组件传递的回调函数传入数据
- 父组件如何接收子组件的数据?
- 回调函数的参数是子组件传递的数据
- 父组件数据更新后,传递给子组件的数据是否更新?
- 自动更新
6. 组件通讯-兄弟组件通讯
通过状态提升思想完成兄弟组件数据通讯
大致步骤:
- 状态提升思想是什么?
- 演示通过状态提升完成兄弟组件通讯。
具体内容:
① 状态提升思想是什么?
- 将共享状态提升到最近的公共父组件中,由公共父组件管理这个状态和修改状态的方法
- 需要通讯的组件通过 props 接收状态和函数即可
② 参考代码
index.js
import React, { Component } from 'react';
import ReactDOM from 'react-dom';// 导入两个子组件
import Jack from './Jack';
import Rose from './Rose';// App 是父组件
class App extends Component {// 1. 状态提升到父组件state = {msg: '',};changeMsg = (msg) => {this.setState({ msg });};render() {return (<div><h1>我是App组件</h1>{/* 兄弟组件 1 */}<Jack changeMsg={this.changeMsg}></Jack>{/* 兄弟组件 2 */}<Rose msg={this.state.msg}></Rose></div>);}
}// 渲染组件
ReactDOM.render(<App />, document.getElementById('root'));
- Jack.js
import React, { Component } from 'react';export default class Jack extends Component {say = () => {// 修改数据this.props.changeMsg('you jump i look');};render() {return (<div><h3>我是Jack组件</h3><button onClick={this.say}>说</button></div>);}
}
- Rose.jsx
import React, { Component } from 'react';export default class Rose extends Component {render() {return (<div><h3>我是Rose组件-{this.props.msg}</h3></div>);}
}
7. 组件通讯-context 跨级组件通讯
掌握使用 context 实现跨级组件通讯
大致步骤:
- 什么是跨级组件通讯?
- context 怎么去理解?
- 演示使用 context 完成跨级组件通讯。
具体内容:
什么是跨级组件通讯?
① 组件间相隔多层,理解成叔侄,甚至更远的亲戚。
② context 怎么去理解
- 术语:上下文
- 理解:一个范围,只要在这个范围内,就可以跨级组件通讯。(不需要 props 层层传递)
③ context使用方法
- 创建上下文
import { createContext } from 'react' // 引入创建上下文的方法
export default createContext(初始值) // 初始值会在找不到Provider提供者时生效
- 使用上下文的Provider组件作为提供者
import Context from './context'function Parent () {return <Context.Provider value={context共享的值}>....子孙组件</Context.Provider>}
- 使上下文的Consumer作为消费者
import Context from './context'
function Child () {return <Context.Consumer>{value => JSX}</Context.Consumer>
}
创建上下文对象,上下文对象存在提供者和消费者,提供者提供数据,消费者消费数据
总结:
- 使用
creatContext()
创建一个上下文对象,包含:Provider
Consumer
组件。 - 使用
Provider
包裹组件,value
属性注入状态,函数
,被包裹组件下的任何组件可以使用。 - 使用
Consumer
消费Provider
提供的数据和函数,语法{value=>使用数据和函数}
8. props-children 属性
掌握 props 中 children 属性的用法
大致步骤:
- props 中 children 属性代表什么?
- props 中 children 属性的使用
- 使用 props 中 children 属性 封装
NavBar
组件
具体内容:
① props 中 children 属性代表什么?
- 组件标签的子节点(标签之间的内容),可以是任意值(文本,React 元素,组件,函数)
② props 中 children 属性的使用
// 定义组件
const Hello = (props) => {return <div>该组件的子节点:{props.children}</div>;
};
// 使用组件
<Hello>我是子节点</Hello>;
③ 使用 props 中 children 属性 封装 NavBar
组件
import React, { Component } from 'react';const NavBar = (props) => {return <h3>< {props.children}</h3>;
};export default class App extends Component {render() {return (<><NavBar>文章详情</NavBar><NavBar>文章列表</NavBar><NavBar>我的<span style={{ color: 'red' }}>点赞</span></NavBar></>);}
}
9. props-类型校验
校验接收的props的数据类型,增加组件的稳健性
大致步骤:
- 理解props都是外来的,在使用的时候如果数据类型不对,很容易造成组件内部逻辑出错
- 通过 prop-types 可以在创建组件的时候进行类型检查,更合理的使用组件避免错误
具体内容:
① 理解props都是外来的,在使用的时候如果数据类型不对,很容易造成组件内部逻辑出错
// 开发者A创建的组件
const List = props => {const arr = props.colorsconst list = arr.map((item, index) => <li key={index}>{item.name}</li>)return (<ul>{list}</ul>)
}// 开发者B去使用组件
<List colors={19} />
报错:
TypeError: arr.map is not a function
② 通过 prop-types 可以在创建组件的时候进行类型检查,更合理的使用组件避免错误
- 安装
yarn add prop-types(脚手架创建自带这个包)
- 导入
import PropTypes from 'prop-types'
- 使用
组件名.propTypes = { 'props属性':'props校验规则' }
进行类型约定,PropTypes
包含各种规则
import PropTypes from 'prop-types'const List = props => {const arr = props.colorsconst lis = arr.map((item, index) => <li key={index}>{item.name}</li>)return <ul>{lis}</ul>
}List.propTypes = {// props属性:校验规则colors: PropTypes.array
}
总结:
- 在提供组件的时候,props校验可以让组件使用更加准确。
10. props-类型校验常见类型
了解react组件props校验的常见规则
大致步骤:
- 了解常见的校验规则
- 演示校验规则的使用
具体内容:
-
了解常见的校验规则
- 常见类型:array、bool、func、number、object、string
- React元素类型:element
- 必填项:isRequired
- 特定结构的对象:shape({})
-
演示校验规则的使用
const Demo = (props) => {return <div>Demo组件</div>
}
Demo.propTypes = {// 常见类型optionalFunc: PropTypes.func,// 常见类型+必填requiredFunc: PropTypes.func.isRequired,// 特定结构的对象optionalObjectWithShape: PropTypes.shape({color: PropTypes.string,fontSize: PropTypes.number})
}
总结:
- 通过
PropTypes
可以得到常见的校验规则
11. props-默认值
给组件的props提供默认值
大致步骤:
- 知道
defaultProps
的作用? - 演示如何设置props的默认值
- 新版react推荐使用参数默认值来实现
具体内容:
① 知道 defaultProps
的作用
- 给组件的props设置默认值,在未传入props的时候生效
② 如何设置props的默认值参考代码
// 分页组件
const Pagination = (props) => {return <div> pageSize的默认值:{props.pageSize}</div>
}
// 设置默认值
Pagination.defaultProps = {pageSize: 10
}
// 使用组件
<Pagination />
③ 新版react推荐使用参数默认值
来实现
// 分页组件
const Pagination = ({pageSize = 10}) => {return <div> pageSize的默认值:{pageSize}</div>
}
// 使用组件
<Pagination />
总结:
组件名称.defaultProps
可以设置props属性默认值,未传的时候使用- 新版 react 更推荐
参数默认值
来实现
12. props-静态属性写法
知道在类组件中如何设置 类型校验 和 默认值
大致步骤:
- 类的静态属性写法和如何访问它
- 类组件中
propTypes
defaultProps
的使用代码参考
具体内容:
① 类的静态属性写法和如何访问它
- 实例属性需要实例化后,通过实例访问
- 静态属性,可以通过类直接访问
class Person {// 实例成员constructor (name, age) {this.name = namethis.age = age}// 实例方法sayHi () {console.log('Hi')}// static 关键字: 静态成员static aa = 'bb'
}// 实例成员: 通过实例调用的属性或者方法,叫做实例成员(属性或者方法)
const p = new Person('刘建超', 20)
console.log(p.age)
p.sayHi()// 静态成员: 通过类或者构造函数本身才能访问的属性或者方法
Person.username = '人'
console.log(p.username) //undefined
console.log(Person.username) //人
console.log(Person.aa) // bb
② 类组件中 propTypes
defaultProps
的使用代码参考
class Demo extends Component {// 校验static propTypes = {colors: PropTypes.array,gender: PropTypes.oneOf(['男', '女']).isRequired}// 默认值static defaultProps = {gender: '男'}render() {return <div>Demo组件</div>}
}
总结:
- 在类组件中通过
static propTypes = {}
定义props校验规则static defaultProps = {}
定义props默认值