组件间通信
父组件向子组件通信
这是最简单也是最常见的一种通信方式。父组件通过向组件间传递props,组件得到props后进行相应的处理。
父组件:
import Child from './Child'
class Father extends Component {
render(){
return(
<Child title = "子组件的title 由父组件传递" />
)
}
}
子组件:
class Child extends Component{
constructor(){
super(props)
}
render(){
return <h1>{ this.props.title }</h1>
}
}
子组件向父组件通信
child组件通知父组件,主要依靠parent传下来的回调函数执行,改变parent组件的状态。
场景1: 子组件要修改父组件的状态state
方法: 父组件传递一个函数 作为子组件的props,这个函数包含父组件的setState方法,并且接收一个参数,表示父组件 新的state
class Father extends Component {
constructor(){
super()
this.state ={ value:'' }
}
// 作为参数要传递的 函数
setValue = value =>{
this.setState({
value
})
}
render(){
return (
<div>
<div>我是父组件,value是:{ this.state.value }<div>
<Child setValue = { this.setValue } />
</div>
)
}
}
class Child extends Component {
constructor(){
super(props)
this.state ={ inputValue:''}
}
// 监听输入框变化
handleInputChange = e => {
this.setState({
inputValue:e.target.value
})
}
handleDivClick = () => {
// 从props接收一个函数 该函数中包含父组件 的setState方法
const { setValue } = this.props
// 将新的数据 作为参数 执行这个函数
setValue(this.state.inputValue)
// 执行这个函数 父组件的state发生变化,触发re-render
}
render(){
return (
<div>
<div>我是子组件</div>
<input onChange ={ this.handleInputChange }>
<div onClick ={ this.handleDivClick }>点击就能改变父组件的状态</div>
</div>
)
}
}
场景2 state定义在子组件中
有时候父组件只是需要拿到子组件的state
因此可以在父组件定义一个函数,接收子组件的state,然后将这个函数以props的形式传递给子组件。
子组件通过this.prop.属性名,拿到这个函数,将子组件本身的state作为函数参数,然后执行这个函数即可。
// parent
class Parent extends Component {
onChange = value => {
console.log(value, '来自 child 的 value 变化');
}
render() {
return (
<div>
<div>我是parent
<Child onChange={this.onChange} />
</div>
);
}
}
class Child extends Component {
constructor() {
super();
this.state = {
childValue: ''
}
}
childValChange = e => {
this.childVal = e.target.value;
}
childValDispatch = () => {
const { onChange } = this.props;
this.setState({
childValue: this.childVal,
}, () => { onChange(this.state.childValue) })
}
render() {
return (
<div>
我是Child
<div className="card">
state 定义在 child
<input onChange={this.childValChange} />
<div className="button" onClick={this.childValDispatch}>通知</div>
</div>
</div>
);
}
}
兄弟组件间通信
方式1 依赖共同的container
有时候出现页面中的某两部分通信,组件并不是父子级别,没有嵌套关系的时候,这种时候通常是依赖共有的顶级container处理或者是第三方的状态管理器。
原理:
兄弟A的value发生变化,分发的时候把value值告诉一个中间者C,C会自动告诉B,实现B的自动render。
// container
class Container extends Component {
constructor() {
super();
this.state = {
value: '',
}
}
setValue = value => {
this.setState({
value,
})
}
render() {
return (
<div>
<A setValue={this.setValue}/>
<B value={this.state.value} />
</div>
);
}
}
// 兄弟A
class A extends Component {
handleChange = (e) => {
this.value = e.target.value;
}
handleClick = () => {
const { setValue } = this.props;
setValue(this.value);
}
render() {
return (
<div className="card">
我是Brother A, <input onChange={this.handleChange} />
<div className="button" onClick={this.handleClick}>通知</div>
</div>
)
}
}
// 兄弟B
const B = props => (
<div className="card">
我是Brother B, value是:
{props.value}
</div>
);
export default B;
利用一个共同的container,兄弟A根据子组件向父组件传值的方式,将自己的state更新到container中,而兄弟B则根据父祖件传值给子组件的方式,直接从props拿到新的state。
方式2 利用Context
上面的方式,如果嵌套少还可以,如果嵌套多层,就很复杂了。每一层组件都要传递一次。
参考 React基础(4) Context上下文