三、组件通信
1,父子组件通信
父组件向子组件通信是通过父组件向子组件的props传递数据完成的,子组件需要改变父组件数据时,调用 父组件通过props传递给子组件 的回调函数。
class Hello extends Component { constructor(props) { super(props); this.state= { name: 'sxww' }; this.updateName = this.updateName.bind(this); } updateName(){ this.setState({ name: 'zzz' }) } render() { return ( <div> <User name={this.state.name} updateName={this.updateName}></User> </div> ) } } export default Hello;
在User中,通过this.props.updateName()改变父组件数据。
2,兄弟组件通信
兄弟组件之间不能相互传送数据,需要通过状态提升实现兄弟组件的通信,即把组件之间需要共享的状态保存到距离它们最近的共同父组件内,任何一个兄弟组件都可以通过父组件传递的回调函数来修改共享状态,父组件中共享状态的变化也会通过prosp向下传递给所有兄弟组件,从而完成兄弟组件之间的通信。
class Hello extends Component { constructor(props) { super(props); this.state= { name: 'sxww', age: 26 }; this.updateName = this.updateName.bind(this); } updateName(){ this.setState({ name: 'zzz', age: 28 }) } render() { return ( <div> <User updateName={this.updateName}></User> <Detail name={this.state.name} age={this.state.age}></Detail> </div> ) } } export default Hello;
在User中,通过this.props.updateName()改变父组件数据,修改后的数据表现到Detail中。
3,context上下文
当应用更加复杂时,组件层级会更多,组件通信就需要通过更多层级的传递,组件通信会变得非常麻烦。context让任意层级的子组件都可以获取父组件的状态和方法。
创建context的方法是:在提供context的组件内新增一个getChildContext方法,返回context对象,然后在组件的childContextTypes属性上定义context对象的属性的类型信息。
class UserList extends Component { constructor(props) { super(props); this.state= { name: 'sxww', age: 26 }; this.updateName = this.updateName.bind(this);
this.getChildContext = this.getChildContext.bind(this); } getChildContext(){ return { updateName: this.updateName } } updateName(){ this.setState({ name: 'zzz', age: 28 }) } render() { return ( <div> <User updateName={this.updateName}></User> <Detail name={this.state.name} age={this.state.age}></Detail> </div> ) } } UserList.childContextTypes = { updateName: PropTypes.func } export default UserList;
class User extends Component { constructor(props) { super(props); } handleClick(){ this.context.updateName(); } render() { return ( <div> <button onClick={this.handleClick}>Set</button> </div> ) } } // 声明要使用的context对象的属性 User.contextTypes = { updateName: PropTypes.func } export default User;
缺点:过多的context会让应用的数据流变得混乱,而且context是一个实验性的API,未来可能被废弃。
4,延伸
- 通过引入EventEmitter或Postal.js等消息队列库:改变数据的组件发起一个消息,使用数据的组件监听这个消息,并在响应函数中触发setState来改变组件状态——观察者模式。
- 引入专门的状态管理库实现组件通信和组件状态管理。