We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
在这里只讲 React 组件与组件本身的通信,组件通信主要分为三个部分:
父组件向子组件传参 父组件向子组件参可以在子组件上绑定自定义属性,或者将父组件内部 state 的值进行绑定为子组件的属性值进行传递。
父组件调用子组件的方法 在子组件上绑定 ref 属性,并在子组件内部定义方法(可接受参数),在父组件内部使用this.refs.自定义属性值.函数方法名,进行调用,可传递参数。
this.refs.自定义属性值.函数方法名
components/parentToChild/Parent.js
// 父组件 import React from 'react'; import Child from './child'; class Parent extends React.Component { constructor(props) { super(props); this.state = { value: '' }; } handleChange(e) { this.value = e.target.value; // 调用子组件的方法 this.refs.c1.changeChild(this.value); } handleClick() { this.setState({ value: this.value }); } render() { return ( <div> 我是parent <input onChange={this.handleChange.bind(this)} /> <button className="button" onClick={this.handleClick.bind(this)}> 通知 </button> <div> <Child ref="c1" value={this.state.value} /> </div> </div> ); } } export default Parent;
// 子组件 import React from 'react'; class Child extends React.Component { constructor(props) { super(props); this.state = { text: '' }; } changeChild(text) { this.setState({ text: text }); } render() { return ( <div> <p>我是Child,接受来自父组件的传参:{this.props.value}</p> <br /> <p>我是child,来自父组件对组件内部函数的的调用:{this.state.text}</p> </div> ); } } export default Child;
import React from 'react'; import './App.css'; import ParentToChild from './components/parentToChild/Parent'; class App extends React.Component { render() { return ( <div className="App"> {/* 父传子 */} {/* <ParentToChild /> */} </div> ); } } export default App;
子组件向父组件传值,在被调用的子组件上先定义回调函数,再来单独的子组件上定义新的函数,通过 props 获取 callback 函数进行值传递.
这里的 state 可以分别定义在父组件或组子组件上
// Father import React from 'react'; import Son from './son'; class Father extends React.Component { constructor(props) { super(props); this.state = { value: '' }; } setValue(param) { this.setState({ value: param }); } render() { return ( <div> <Son setValue={this.setValue.bind(this)}></Son> <p>我是Father,接受子组件的传参:{this.state.value}</p> </div> ); } } export default Father;
// son import React from 'react'; class Son extends React.Component { constructor(props) { super(props); this.state = { text: '' }; } handleChange(e) { this.props.setValue(e.target.value); } render() { return ( <div> 我是Son <input onChange={this.handleChange.bind(this)} /> <br /> </div> ); } } export default Son;
import React from 'react'; import './App.css'; import SonToFather from './components/sonToFather/Father'; class App extends React.Component { render() { return ( <div className="App"> {/* 子传父 */} <SonToFather /> </div> ); } } export default App;
先将两个子组件child1和child2的参数传递给父组件,再由分发参数,通过refs寻找函数方法的方式进行函数调用传参。
child1
child2
refs
// Parent class Parent extends React.Component { constructor(props) { super(props); this.state = { value: '' }; } setValue2(param) { this.refs.c1.changeState(param); this.setState({ value: param }); } setValue1(param) { this.refs.c2.changeState(param); this.setState({ value: param }); } render() { return ( <div> <p>我是Parent,接受子组件的传参:{this.state.value}</p> <Child1 ref="c1" setValue={this.setValue1.bind(this)}></Child1> <Child2 ref="c2" setValue={this.setValue2.bind(this)}></Child2> </div> ); } }
// Child1 class Child1 extends React.Component { constructor(props) { super(props); this.state = { text: '' }; } handleChange(e) { this.props.setValue(e.target.value); } changeState(text) { this.setState({ text: text }); } render() { return ( <div> 我是child1 <input onChange={this.handleChange.bind(this)} /> <p>来自子组件2的调用: {this.state.text}</p> <br /> </div> ); } }
// Child2 class Child2 extends React.Component { constructor(props) { super(props); this.state = { text: '' }; } handleChange(e) { this.props.setValue(e.target.value); } changeState(text) { this.setState({ text: text }); } render() { return ( <div> 我是child1 <input onChange={this.handleChange.bind(this)} /> <p>来自子组件1的调用: {this.state.text}</p> <br /> </div> ); } }
// 父组件 var Parent = React.createClass({ getChildContext: function() { return { changeChildren1: function(text) { this.refs.cp1.changeState(text); }.bind(this), changeChildren2: function(text) { this.refs.cp2.changeState(text); }.bind(this) }; }, childContextTypes: { changeChildren1: React.PropTypes.func.isRequired, changeChildren2: React.PropTypes.func.isRequired }, render: function() { return ( <div> <Children1 ref="cp1" /> <Children2 ref="cp2" /> </div> ); } });
//子组件1 var Children1 = React.createClass({ getInitialState: function() { return { text: '' }; }, contextTypes: { changeChildren2: React.PropTypes.func.isRequired }, changeState: function(text) { this.setState({ text: text }); }, //输入事件 change: function(event) { //调用子组件的方法 this.context.changeChildren2(event.target.value); }, render: function() { return ( <div> <p> <label>子组件1</label> <input type="text" onChange={this.change} /> </p> <p>来自子组件2的调用-{this.state.text}</p> </div> ); } });
//子组件2 var Children2 = React.createClass({ getInitialState: function() { return { text: '' }; }, contextTypes: { changeChildren1: React.PropTypes.func.isRequired }, changeState: function(text) { this.setState({ text: text }); }, //输入事件 change: function(event) { //调用子组件的方法 this.context.changeChildren1(event.target.value); }, render: function() { return ( <div> <p> <label>子组件2</label> <input type="text" onChange={this.change} /> </p> <p>来自子组件1的调用-{this.state.text}</p> </div> ); } });
在 componentDidMount 事件中,如果组件挂载完成,再订阅事件;在组件卸载的时候,在 componentWillUnmount 事件中取消事件的订阅;以常用的发布/订阅模式举例,借用 Node.js Events 模块的浏览器版实现
先引入 node events 模块
events
yarn add events
在 src 下新建一个 util 目录里面建一个 events.js
import { EventEmitter } from 'events'; export default new EventEmitter();
import React, { Component } from 'react'; import emitter from '../../util/events'; class List1 extends Component { constructor(props) { super(props); this.state = { message: 'List1' }; } componentDidMount() { // 组件装载完成以后声明一个自定义事件 this.eventEmitter = emitter.addListener('changeMessage', message => { this.setState({ message }); }); } componentWillUnmount() { emitter.removeListener(this.eventEmitter); } render() { return ( <div> {this.state.message} {this.props.msg} </div> ); } } export default List1;
import React, { Component } from 'react'; import emitter from '../../util/events'; class List2 extends Component { handleClick = message => { emitter.emit('changeMessage', message); }; handleClick2 = message => { emitter.emit('changeMessageApp', message); }; render() { return ( <div> <button onClick={this.handleClick.bind(this, 'List2')}> 点击我改变List1组件中显示信息 </button> <button onClick={this.handleClick2.bind(this, 'List2App')}> 点击我改变App组件中显示信息 </button> </div> ); } } export default List2;
APP.js
import React from 'react'; import './App.css'; import List1 from './components/eventCenter/List1'; import List2 from './components/eventCenter/List2'; import emitter from './util/events'; class App extends React.Component { constructor(props) { super(props); this.state = { message: 'msgFromApp' }; } componentDidMount() { // 组件装载完成以后声明一个自定义事件 this.eventEmitter = emitter.addListener('changeMessageApp', message => { this.setState({ message }); }); } render() { return ( <div className="App"> <List1 msg={this.state.message} /> <List2 /> </div> ); } } export default App;
此方法还支持子父组件的传值,但考虑到消息中心的可维护性,易维护性,采用以下的方法
Redux || Mobx
The text was updated successfully, but these errors were encountered:
No branches or pull requests
组件通信
在这里只讲 React 组件与组件本身的通信,组件通信主要分为三个部分:
父传子
父组件向子组件传参
父组件向子组件参可以在子组件上绑定自定义属性,或者将父组件内部 state 的值进行绑定为子组件的属性值进行传递。
父组件调用子组件的方法
在子组件上绑定 ref 属性,并在子组件内部定义方法(可接受参数),在父组件内部使用
this.refs.自定义属性值.函数方法名
,进行调用,可传递参数。components/parentToChild/Parent.js
子传父
子组件向父组件传值,在被调用的子组件上先定义回调函数,再来单独的子组件上定义新的函数,通过 props 获取 callback 函数进行值传递.
兄弟组件
利用共同的父组件
先将两个子组件
child1
和child2
的参数传递给父组件,再由分发参数,通过refs
寻找函数方法的方式进行函数调用传参。利用 Context
发布订阅
先引入 node
events
模块在 src 下新建一个 util 目录里面建一个 events.js
APP.js
主流通信库
Redux || Mobx
参考文章
The text was updated successfully, but these errors were encountered: