1.什么是组件通讯
组件是独立且封闭的单元,默认情况下,只能使用自己的数据。在组件化过程中,我们将一个完整的功能拆分为多个组价,以更好的完成整个应用的功能。而在这个过程中,多个组件不可避免地要共享某些数据。为了实现这些功能,就需要打破组件的独立封闭性,让其与外界沟通,这个过程就是组件通讯。
2.组件的props
- 组件是封闭的,接收传递外部数据应该通过props来实现
- props的作用:接收传递给组件的数据
- 传递数据:给组件标签添加属性
- 接收数据:函数组件通过参数props接收数据,类组件通过this.props接收数据
//函数组件
import React from 'react';
import ReactDOM from 'react-dom';
//可以写成箭头函数的形式
function Hello(props){
console.log(props)
return(
<div>接收到的数据:{props.name}</div>
)
}
ReactDOM.render(<Hello name='jack'></Hello>,document.getElementById('root'))
//类组件
class Hello extends React.Component{
render(){
return(
<div>接收到的数据:{this.props.age}</div>
)
}
}
ReactDOM.render(<Hello name='jack' age={21}></Hello>,document.getElementById('root'))
3.组件props的特点
- 可以给组件传递任意类型的数据
- props是只读的对象,只能读取属性的值,无法修改对象
- 注意:使用类组件,如果写了构造函数,应该将props传递给super(),否则,无法构造函数中获取到props
//
class Hello extends React.Component{
constructor(props){
super(props)//推荐将props传递给父类构造函数
}
render(){
return(
<div>接收到的数据:{this.props.age}</div>
)
}
}
ReactDOM.render(<Hello name='jack' age={21}></Hello>,document.getElementById('root'))
//传递任意数据类型
class Hello extends React.Component{
constructor(props){
super(props)
}
render(){
return(
<div>接收到的数据:{this.props.age},{this.props.colors},{this.props.fn()},
{this.props.tag}</div>
)
}
}
ReactDOM.render(<Hello
tag={<p>这是一个p标签</p>}
fn={()=>console.log('这是一个函数')}
colors={['red','green','blue']}
name='jack'
age={21}>
</Hello>,
document.getElementById('root'))
4.组件通讯的三种方式
4.1父组件传递数据给子组件
- 父组件提供要传递的state数据
- 给子组件标签添加属性,值为state中的数据
- 子组件中通过props接收父组件传递的数据
//父组件
class Parent extends React.Component{
state = {lastName:'黄'}
render(){
return(
<div>
传递给子组件:{<Child name={this.state.lastName}/>}
</div>
)
}
}
//
//子组件
function Child(props){
console.log(props)
return <div>子组件接收到的数据{props.name}</div>
}
ReactDOM.render(<Parent/>,//调用的是父组件
document.getElementById('root'))
4.2子组件传递给父组件
思路:利用回调函数,父组件提供回调,子组件调用,将要传递的数据作为回调函数的参数
- 父组件提供一个回调函数(用于接收数据)
- 将该函数作为属性的值,传递给子组件
//父组件
class Parent extends React.Component{
//提供回调函数
getChild = (msg) =>{
console.log('接收到子组件数据',msg)
}
state = {lastName:'黄'}
render(){
return(
<div>
传递给子组件:{<Child getMsg={this.getChild}/>}
</div>
)
}
}
//子组件
class Child extends React.Component{
state={
childMag:'React'
}
handleClick = ()=>{
this.props.getMsg(this.state.childMag)
}
render(){
return(
<button onClick={this.handleClick}>点我,给父组件传递数据</button>
)
}
}
ReactDOM.render(<Parent/>,//调用的是父组件
document.getElementById('root'))
4.3兄弟组件通讯
- 将共享状态提升到最近的公共父组件中,由公共父组件管理这个状态
- 思想:状态提升
- 公共父组件的职责:1.提供共享状态2.提供操作共享状态的方法
- 要通讯的子组件只需通过props接收状态或操作状态的方法
const valueContext = React.createContext('pink')
class App extends React.Component{
render(){
return(
// <Provider>
<valueContext.Provider value='dark'>
<div className='app' >
<Node/>
</div>
</valueContext.Provider>
)
}
}
//子组件
const Node = props =>{
return(
<div className='node'>
<SunNode/>
</div>
)
}
//子组件
const SunNode = props=>{
return(
<div className='subnode'>
<Child/>
</div>
)
}
class Child extends React.Component{
static contextType = valueContext;
render(){
return(
<div className='child'>
{this.context}
</div>
)
}
}
ReactDOM.render(<App/>,//调用的是父组件
document.getElementById('root'))
可参考文档:https://zh-hans.reactjs.org/docs/context.html#reactcreatecontext
const{Provider,Consumer} = React.createContext()
// const valueContext = React.createContext('pink')
class App extends React.Component{
render(){
return(
<Provider value='dark'>
{/* <valueContext.Provider > */}
<div className='app' >
<Node/>
</div>
{/* </valueContext.Provider> */}
</Provider>
)
}
}
//子组件
const Node = props =>{
return(
<div className='node'>
<SunNode/>
</div>
)
}
//子组件
const SunNode = props=>{
return(
<div className='subnode'>
<Child/>
</div>
)
}
class Child extends React.Component{
// static contextType = valueContext;
render(){
return(
<div className='child'>
<Consumer>{data => <span>data的值为:{data}</span>}</Consumer>
{/* {this.context} */}
</div>
)
}
}
ReactDOM.render(<App/>,//调用的是父组件
document.getElementById('root'))