295 lines
7.3 KiB
Markdown
295 lines
7.3 KiB
Markdown
|
# 组件通讯
|
||
|
多组件之间共享通讯
|
||
|
## props接收传递给组件的数据
|
||
|
传递数据:给组件标签添加属性
|
||
|
函数组件 props
|
||
|
```html
|
||
|
const HelloProps = (props)=>{
|
||
|
console.log(props)
|
||
|
return (
|
||
|
<div>props:{props.name}</div>
|
||
|
)
|
||
|
}
|
||
|
|
||
|
ReactDOM.render(<HelloProps name= "hua"/>,document.getElementById('root'))
|
||
|
```
|
||
|
类组件 this.props
|
||
|
```html
|
||
|
class HelloProps extends React.Component{
|
||
|
render(){
|
||
|
return (<div>props:{this.props.name},{this.props.role}</div>)
|
||
|
}
|
||
|
}
|
||
|
ReactDOM.render(<HelloProps name= "hua" role="shi"/>,document.getElementById('root'))
|
||
|
|
||
|
```
|
||
|
## 组件特点
|
||
|
1. 可以是任意值
|
||
|
```html
|
||
|
class HelloProps extends React.Component{
|
||
|
render(){
|
||
|
console.log(this.props)
|
||
|
return (<div>props:{this.props.name},{this.props.role} {this.props.tag}</div>)
|
||
|
}
|
||
|
}
|
||
|
ReactDOM.render(<HelloProps name= "hua" role="shi" age = {19}
|
||
|
colors = {['red','green','blue']}
|
||
|
fn={()=>console.log('我可以传函数')}
|
||
|
tag={<p>jsx</p>}
|
||
|
|
||
|
/>,document.getElementById('root'))
|
||
|
```
|
||
|
2. 只读
|
||
|
3. 在使用类组件时,如果写了构造函数,应该将props传递给super(),否则,无法在构造函数中获取到props
|
||
|
|
||
|
```html
|
||
|
class HelloProps extends React.Component{
|
||
|
constructor(props){
|
||
|
super(props)
|
||
|
console.log(this.props)
|
||
|
}
|
||
|
render(){
|
||
|
console.log(this.props)
|
||
|
return (<div>props:{this.props.name},{this.props.role} {this.props.tag}</div>)
|
||
|
}
|
||
|
}
|
||
|
ReactDOM.render(<HelloProps name= "hua" role="shi" age = {19}
|
||
|
colors = {['red','green','blue']}
|
||
|
fn={()=>console.log('我可以传函数')}
|
||
|
tag={<p>jsx</p>}
|
||
|
|
||
|
/>,document.getElementById('root'))
|
||
|
```
|
||
|
## 通讯的三种方式
|
||
|
### 父组件传递给子组件
|
||
|
1. 父组件提供传递的state数据
|
||
|
2. 给子组件添加属性,值为state中的数据
|
||
|
3. 子组件中通过props接收父组件中传递的数据
|
||
|
```html
|
||
|
class Parent extends React.Component{
|
||
|
state = {lastName:'师'}
|
||
|
render(){
|
||
|
return (
|
||
|
<div className='parent'>
|
||
|
父组件:
|
||
|
<Child name = {this.state.lastName}/>
|
||
|
</div>
|
||
|
)
|
||
|
}
|
||
|
}
|
||
|
// 子组件
|
||
|
const Child = (props)=>{
|
||
|
return (
|
||
|
<div className='child'>
|
||
|
<p>子组件接收到父组件的数据 {props.name}</p>
|
||
|
</div>
|
||
|
)
|
||
|
}
|
||
|
|
||
|
ReactDOM.render(<Parent />,document.getElementById('root'))
|
||
|
```
|
||
|
### 子组件传递给父组件
|
||
|
利用回调函数,父组件提供回调,子组件调用,将要传递的数据作为回调函数的参数.
|
||
|
1. 父组件提供一个回调函数(用于接收数据)
|
||
|
2. 将改函数作为属性的值,传递给子组件
|
||
|
3. 子组件通过props调用回调函数
|
||
|
4. 将子组件的数据作为参数传递给回调函数
|
||
|
```html
|
||
|
class Parent extends React.Component{
|
||
|
state={
|
||
|
parentMsg:''
|
||
|
}
|
||
|
|
||
|
getChildMsg = data=>{
|
||
|
console.log('接收到子组件传递过来的数据',data)
|
||
|
this.setState({
|
||
|
parentMsg:data
|
||
|
})
|
||
|
}
|
||
|
render(){
|
||
|
return (
|
||
|
<div className='parent'>
|
||
|
父组件:{this.state.parentMsg}
|
||
|
<Child name = {this.getChildMsg}/>
|
||
|
</div>
|
||
|
)
|
||
|
}
|
||
|
}
|
||
|
// 子组件
|
||
|
class Child extends React.Component{
|
||
|
state = {
|
||
|
msg:"回调传递"
|
||
|
}
|
||
|
handleClick=()=>{
|
||
|
//
|
||
|
this.props.name(this.state.msg)
|
||
|
}
|
||
|
render(){
|
||
|
return (
|
||
|
<div className='child'>
|
||
|
<p>子组件发送到父组件</p><button onClick={this.handleClick}>点击</button>
|
||
|
</div>
|
||
|
)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ReactDOM.render(<Parent />,document.getElementById('root'))
|
||
|
```
|
||
|
## 兄弟组件间的通讯
|
||
|
将共享状态提升到最近的公共父组件中,由公共父组件管理这个状态
|
||
|
状态提升
|
||
|
公共父组件职责:1.提供共享状态2.提供操作共享状态的方法
|
||
|
要通讯的子组件只能通过props接收状态或者操作状态的方法
|
||
|
```html
|
||
|
class Counter extends React.Component{
|
||
|
state={
|
||
|
count:0
|
||
|
}
|
||
|
onIncrement=()=>{
|
||
|
this.setState({
|
||
|
count:this.state.count+1
|
||
|
})
|
||
|
}
|
||
|
render(){
|
||
|
return(
|
||
|
<div>
|
||
|
<Child1 count={this.state.count}></Child1>
|
||
|
<Child2 onIncrement={this.onIncrement}></Child2>
|
||
|
</div>
|
||
|
)
|
||
|
}
|
||
|
}
|
||
|
const Child1=(props)=>{
|
||
|
return <h3>计数器:{props.count}</h3>
|
||
|
}
|
||
|
const Child2=(props)=>{
|
||
|
return <button onClick = {()=>props.onIncrement()}>+1</button>
|
||
|
}
|
||
|
ReactDOM.render(<Counter />,document.getElementById('root'))
|
||
|
```
|
||
|
|
||
|
# Context跨组件传递数据
|
||
|
1. 使用React.createContext()创建Provider,Consumer
|
||
|
2. 使用Provide组件作为父节点
|
||
|
3. 设置value属性,表示要传递的数据
|
||
|
4. 调用Consumer组件来接收数据
|
||
|
```html
|
||
|
const { Provider, Consumer } = React.createContext();
|
||
|
|
||
|
class ContextApp extends React.Component {
|
||
|
render() {
|
||
|
return (
|
||
|
<Provider value='pink'>
|
||
|
<div className="app">
|
||
|
<Node />
|
||
|
</div>
|
||
|
</Provider>
|
||
|
)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
const Node = props => {
|
||
|
return (
|
||
|
<div className="node">
|
||
|
<SubNode />
|
||
|
</div>
|
||
|
)
|
||
|
}
|
||
|
|
||
|
const SubNode = props => {
|
||
|
return (
|
||
|
<div className="subNode">
|
||
|
<Child />
|
||
|
</div>
|
||
|
)
|
||
|
}
|
||
|
|
||
|
const Child = props => {
|
||
|
return <div className="child" ><Consumer>{data=><span>我是子节点---{data}</span>}</Consumer></div>
|
||
|
}
|
||
|
```
|
||
|
# props深入
|
||
|
## children表示组件标签的子节点.当组件标签有子节点时,props就会有该属性.
|
||
|
children 属性与普通props一样,值可以是任意值(文本,React元素,组件,甚至是函数)
|
||
|
```html
|
||
|
class ChildProps extends React.Component{
|
||
|
render(){
|
||
|
console.log(this.props)
|
||
|
return (
|
||
|
<div><h2>组件标签的子节点{this.props.children}</h2></div>
|
||
|
)
|
||
|
}
|
||
|
}
|
||
|
ReactDOM.render(<ChildProps>传递到props的child</ChildProps>,document.getElementById('root'))
|
||
|
```
|
||
|
|
||
|
```html
|
||
|
class ChildProps extends React.Component{
|
||
|
render(){
|
||
|
console.log(this.props)
|
||
|
return (
|
||
|
<div><h2>组件标签的子节点</h2>{this.props.children}</div>
|
||
|
)
|
||
|
}
|
||
|
}
|
||
|
const Test = ()=> <button>组件按钮</button>
|
||
|
ReactDOM.render(<ChildProps><Test/><p>传递到props的child</p></ChildProps>,document.getElementById('root'))
|
||
|
```
|
||
|
函数
|
||
|
```html
|
||
|
class ChildProps extends React.Component{
|
||
|
render(){
|
||
|
this.props.children()
|
||
|
console.log(this.props)
|
||
|
return (
|
||
|
<div><h2>组件标签的子节点</h2></div>
|
||
|
)
|
||
|
}
|
||
|
}
|
||
|
ReactDOM.render(<ChildProps>{()=>console.info("这是一个函数")}</ChildProps>,document.getElementById('root'))
|
||
|
```
|
||
|
## prop 校验
|
||
|
1. 安装prop-types (npm i prop-types 或者 yarn add prop-types)
|
||
|
2. 导入prop-types包
|
||
|
3. 使用组件名.propTypes={}来给组件的props添加校验规则
|
||
|
4. 校验规则通过PropTypes对象指定
|
||
|
```html
|
||
|
import React from "react"
|
||
|
import PropTypes from "prop-types"
|
||
|
class PropCheck extends React.Component{
|
||
|
render(){
|
||
|
const arr = this.props.colors
|
||
|
console.info(arr)
|
||
|
const lis = arr.map((item,index)=><li key={index}>{item}</li>)
|
||
|
return (
|
||
|
<ul>{lis}</ul>
|
||
|
)
|
||
|
}
|
||
|
}
|
||
|
PropCheck.protoTypes= {
|
||
|
colors:PropTypes.array
|
||
|
}
|
||
|
export default PropCheck
|
||
|
ReactDOM.render(<PropCheck colors = {['red','black']} />,document.getElementById('root'))
|
||
|
```
|
||
|
## prop 默认值
|
||
|
```html
|
||
|
class LPropCheck extends React.Component{
|
||
|
render(){
|
||
|
// const arr = this.props.colors
|
||
|
// console.info(arr)
|
||
|
// const lis = arr.map((item,index)=><li key={index}>{item}</li>)
|
||
|
// return (
|
||
|
// <ul>{lis}</ul>
|
||
|
// )
|
||
|
return <div><h2>test</h2>{this.props.colors}</div>
|
||
|
}
|
||
|
}
|
||
|
LPropCheck.propTypes= {
|
||
|
colors:PropTypes.array
|
||
|
}
|
||
|
LPropCheck.defaultProps= {
|
||
|
colors:["red"]
|
||
|
}
|
||
|
```
|