目录
组件通讯介绍
组件是独立且封闭的单元,默认情况下,只能使用组件自己的数据。在组件化过程中,我们将一个完整的功能拆分成多个组件,以更好的完成整个应用的功能。而更好的完成整个应用的功能。而在这个过程中,多个组件之间不可避免的要共享某些数据。为了实现这些功能,就需要打破组件的独立封闭性,让其与外界沟通。这个过程就是组件通讯。
组件的props
· 组件是封闭的,要接收外部数据应该通过props来实现
· props的作用:接收传递给组件的数据
· 传递数据:给组件标签添加属性
· 接收数据:函数组件通过参数props接收数据,类组件通过this.props接收数据
import React from 'react';
import ReactDOM from 'react-dom';
import './index.less';
/*props*/
// 函数组件中props演示
const Hello = (props) => {
console.log(props);
//props是一个对象
return (
<div>
<h1>props:{props.name}</h1>
</div>
)
}
ReactDOM.render(<Hello name="xy" age={22}/>, document.getElementById('root'));
import React from 'react';
import ReactDOM from 'react-dom';
import './index.less';
/*props*/
// 类组件中props演示
//2.接收数据
class Hello extends React.Component {
render() {
console.log(this.props);
return (
<div>
<h1>props:{this.props.name}</h1>
</div>
)
}
}
//1.传递数据
ReactDOM.render(<Hello name="xy" age={22}/>, document.getElementById('root'));
特点
1.可以给组件传递任意类型的数据
2.props是只读的对象,只能读取属性的值,无法修改对象
3.注意:使用类组件时,如果写了构造函数,应该将props传递给super(),否则,无法在构造函数中获取到props!
import React from 'react';
import ReactDOM from 'react-dom';
import './index.less';
/*props*/
// 类组件
class Hello extends React.Component {
//推荐使用props作为constructor的参数!
constructor(props) {
super(props)
console.log(props)
}
render() {
console.log('render', this.props);
return (
<div>
<h1>props:{this.props.name}</h1>
</div>
)
}
}
ReactDOM.render(<Hello name="xy" age={22}/>, document.getElementById('root'));
组件通讯的三种方式
1 父组件传递数据给子组件
1.父组件提供要传递的state中的数据
2.给子组件标签添加属性,值为state中的数据
3.子组件中通过props接收父组件中传递的数据
import React from 'react';
import ReactDOM from 'react-dom';
import './index.less';
//父组件
class Parent extends React.Component {
state = {
lastName: '颖'
}
render() {
return (
<div className='parent'>
父组件:
<Child name={this.state.lastName} />
</div>
)
}
}
//子组件
const Child = (props) => {
console.log('子组件', props)
return (
<div className='child'>
<p>子组件,接收到父组件的数据:{props.name}</p>
</div>
)
}
ReactDOM.render(<Parent />, document.getElementById('root'));
2 子组件传递数据给父组件
思路:利用回调函数,父组件提供回调,子组件调用,将要传递的数据作为回调函数的参数。
1.父组件提供一个回调函数(用于接收数据)
2.将该函数作为属性的值,传递给子组件
3.子组件通过props调用回调函数
4.将子组件的数据作为参数传递给回调函数
import React from 'react';
import ReactDOM from 'react-dom';
import './index.less';
//父组件
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 getMsg={this.getChildMsg} />
</div>
)
}
}
//子组件
class Child extends React.Component {
state = {
msg:'吃辣条'
}
handleClick = () => {
//子组件调用父组件中传递过来的回调函数
this.props.getMsg(this.state.msg)
}
render() {
return (
<div className="child">
子组件:<button onClick={this.handleClick}>点我,给父组件传递数据</button>
</div>
)
}
}
ReactDOM.render(<Parent />, document.getElementById('root'));
3 兄弟组件
· 将共享状态提升到最近的公共父组件中,由公共父组件管理这个状态
· 思想:状态提升
· 公共父组件职责:1.提供共享状态 2.提供操作共享状态的方法
· 要通讯的子组件只需通过props接收状态或操作状态的方法
import React from 'react';
import ReactDOM from 'react-dom';
import './index.less';
//父组件
class Counter extends React.Component {
//提供共享状态
state = {
count: 0
}
//提供修改状态的方法
onIncrement = () => {
this.setState({
count:this.state.count + 1
})
}
render() {
return (
<div>
<Child1 count={this.state.count} />
<Child2 onIncrement={this.onIncrement}/>
</div>
)
}
}
const Child1 = (props) => {
return <h1>计数器:{props.count}</h1>
}
const Child2 = (props) => {
return <button onClick={()=>props.onIncrement()}>+1</button>
}
ReactDOM.render(<Counter />, document.getElementById('root'));
思考:若有多个组件嵌套,App组件要传递给Child组件,该如何处理?
· 用props过于繁琐
· 更好的方式:使用Context
· 作用:跨组件传递数据(比如主题、语言等)
使用步骤:
1.调用React.createContext()创建Provider(提供数据)和Consumer(消费数据)两个组件。
2.使用Provider组件作为父节点。
3.设置value属性,表示要传递的数据。
4.调用Consumer组件接收数据。
import React from 'react';
import ReactDOM from 'react-dom';
import './index.less';
/* Context */
// 创建context得到两个组件
// Provider数据的提供者,Consumer数据的消费者
const {Provider,Consumer} = React.createContext()
class App 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>
}
ReactDOM.render(<App />, document.getElementById('root'));