如何解决React中组件通信问题-创新互联

这篇文章将为大家详细讲解有关如何解决React中组件通信问题,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

专业领域包括成都网站设计、成都网站制作、外贸网站建设电子商务商城网站建设、微信营销、系统平台开发, 与其他网站设计及系统开发公司不同,创新互联的整合解决方案结合了帮做网络品牌建设经验和互联网整合营销的理念,并将策略和执行紧密结合,为客户提供全网互联网整合方案。

父子组件

父 → 子

parent组件传给child组件,符合react的单向数据流理念,自上到下传递props。

// 父组件
class Parent extends Component {
 constructor() {
  super();
  this.state = {
   value: '',
  }
 }

 handleChange = e => {
  this.value = e.target.value;
 }

 handleClick = () => {
  this.setState({
   value: this.value,
  })
 }

 render() {
  return (
   
    我是parent          通知
    
          
     
  );  } }
// 子组件
class Child extends Component {
 render() {
  const { value } = this.props;
  return (
   
    我是Child,得到传下来的值:{value}    
  );  } }

父组件做的就是定义好 state ,定义好事件函数,input onChange 的时候,去缓存 value 值,然后点击 button 的时候,改变 state , 子组件只负责展示 value 。

子 → 父

child 组件通知 parent 组件, 主要是依靠 parent 传下来的 callback 函数执行,改变 parent 组件的状态,或者把 child 自己的 state 通知 parent 。分两种情况:

state 定义在 parent 组件

// parent

class Parent extends Component {
 constructor() {
  super();
  this.state = {
   value: '',
  }
 }

 setValue = value => {
  this.setState({
   value,
  })
 }

 render() {
  return (
   
    
我是parent, Value是:{this.state.value}
          
  );  } }
class Child extends Component {

 handleChange = e => {
  this.value = e.target.value;
 }

 handleClick = () => {
  const { setValue } = this.props;
  setValue(this.value);
 }

 render() {
  return (
   
    我是Child           state 定义在 parent            通知
    
   
  );  } }

parent 组件把改变 state 的 setValue 函数传给 child ,child 组件自己处理内部的状态(这里是表单的value值),当 child 组件分发消息的时候, 执行 parent 的 setValue 函数,从而改变了 parent 的 state,state发生变化, parent 组件执行 re-render 。

state 定义在 child 组件

// parent

class Parent extends Component {

 onChange = value => {
  console.log(value, '来自 child 的 value 变化');
 }

 render() {
  return (
   
    
我是parent         
  );  } }
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 (
   
    我是Child           state 定义在 child            通知
    
      );  } }

有时候 state 是需要定义在 child 组件的,比如弹窗, CheckBox 这种开关性质的,逻辑是重复的,state 定义在组件内部更好维护, 复用性更好。但是 child 的 state 是需要告知我的 parent 组件的, 同样还是执行 parent 传下来的 change 函数。

兄弟组件

有时候可能出现页面中的某两部分通信,比如省市的级联选择,点击 button 改变颜色等等,组件并不是父子级,没有嵌套关系的时候。这种时候通常是依赖共有的顶级 Container 处理或者第三方的状态管理器。其实原理都是相通的,兄弟 A 的 value 发生变化,分发的时候把 value 值告诉一个中间者 C ,C 会自动告知 B,实现 B 的自动render 。

利用共有的Container

// container
class Container extends Component {
 constructor() {
  super();
  this.state = {
   value: '',
  }
 }

 setValue = value => {
  this.setState({
   value,
  })
 }

 render() {
  return (
   
             
  );  } }
// 兄弟A
class A extends Component {

 handleChange = (e) => {
  this.value = e.target.value;
 }

 handleClick = () => {
  const { setValue } = this.props;
  setValue(this.value);
 }

 render() {
  return (
   
    我是Brother A, 
    通知
   
  )
 }
}
// 兄弟B
const B = props => (
 
  我是Brother B, value是:
  {props.value}
 
);
export default B;

组件 A 中的表单 value 值,告知了父级 Container 组件(通过 setValue 函数改变 state),组件 B 依赖于 Container 传下来的 state,会做出同步更新。这里的中间者是 Container。

利用Context

上面的方式,如果嵌套少还可以,如果嵌套特别多,比如一级导航栏下的二级导航栏下的某个按钮,要改变页面中 content 区域的 table 里的某个列的值...他们同属于一个 page 。这样传递 props 就会很痛苦,每一层组件都要传递一次。

// 顶级公共组件
class Context extends Component {

 constructor() {
  super();
  this.state = {
   value: '',
  };
 }

 setValue = value => {
  this.setState({
   value,
  })
 }

 getChildContext() { // 必需
  return { 
   value: this.state.value,
   setValue: this.setValue,
  };
 }
 render() {
  return (
   
             
  );  } } // 必需 Context.childContextTypes = {  value: PropTypes.string,  setValue: PropTypes.func, };
// A 的 parent
class AParent extends Component {
 render() {
  return (
   
    
   
  );
 }
}
// A
class A extends Component {

 handleChange = (e) => {
  this.value = e.target.value;
 }

 handleClick = () => {
  const { setValue } = this.context;
  setValue(this.value);
 }

 render() {
  return (
   
    我是parentA 下的 A,      通知
      );  } } // 必需 A.contextTypes = {  setValue: PropTypes.func, };
// B 的 parent
class BParent extends Component {
 render() {
  return (
   
    
   
  );
 }
}

// B
class B extends Component {

 render() {
  return (
   
    我是parentB 下的 B, value是:     {this.context.value}    
  );  } } B.contextTypes = {  value: PropTypes.string, };

组件 A 仍是 消息的发送者,组件 B 是接收者, 中间者是 Context 公有 Container 组件。context是官方文档的一个 API ,通过 getChildContext 函数定义 context 中的值,并且还要求 childContextTypes 是必需的。这样属于这个 Container 组件的子组件,通过 this.context 就可以取到定义的值,并且起到跟 state 同样的效果。中间者其实还是 Container,只不过利用了上下文这样的 API ,省去了 props 的传递。另外:这个功能是实验性的,未来可能会有所改动。

发布订阅

这种一个地方发送消息,另一个地方接收做出变化的需求,很容易想到的就是观察者模式了。具体的实现会有很多种,这里我们自己写了一个 EventEmitter 的类(其实就是仿照 node 中的 EventEmitter 类),如果不了解观察者,可以看我的另一篇文章 观察者模式 。

// 发布订阅类
class EventEmitter {
 _event = {}

 // on 函数用于绑定
 on(eventName, handle) {
  let listeners = this._event[eventName];
  if(!listeners || !listeners.length) {
   this._event[eventName] = [handle];
   return;
  }
  listeners.push(handle);
 }
 // off 用于移除
 off(eventName, handle) {
  let listeners = this._event[eventName];
  this._event[eventName] = listeners.filter(l => l !== handle);
 }
 // emit 用于分发消息
 emit(eventName, ...args) {
  const listeners = this._event[eventName];
  if(listeners && listeners.length) {
   for(const l of listeners) {
    l(...args);
   }
  }
 }
}
const event = new EventEmitter;
export { event };
// Container
import A from './a';
import B from './b';

const Listener = () => {
 return (
  
          
 ); }; export default Listener;
// 兄弟组件 A
import { event } from './eventEmitter';

class A extends Component {

 handleChange = e => {
  this.value = e.target.value;
 }

 handleClick = () => {
  event.emit('dispatch', this.value);
 }

 render() {
  return (
   
    我是Brother A, 
    通知
   
  )
 }
}
// 兄弟组件 B
import { event } from './eventEmitter';

class B extends Component {
 state = {
  value: ''
 }

 componentDidMount() {
  event.on('dispatch', this.valueChange);
 }

 componentWillUnmount() {
  event.off('dispatch', this.valueChange);
 }

 valueChange = value => {
  this.setState({
   value,
  })
 }

 render() {
  return (
   
    我是Brother B, value是:
    {this.state.value}
   
  );
 }
}

仍然是组件 A 用于分发消息,组件 B 去接收消息。这里的中间者其实就是 event 对象。需要接收消息的 B 去订阅 dispatch 事件,并把回调函数 valueChange 传入,另外 B 定义了自己的 state,方便得到 value 值的时候自动渲染。组件 A 其实就是把内部的表单 value 在点击的时候分发,发布事件,从而 B 中的 valueChange 执行,改变 state。这种方式比较方便,也更直观,不需要借助 Container 组件去实现,省去了很多逻辑。

Redux || Mobx

Redux 或者 Mobx 是第三方的状态管理器,是这里我们通信的中间者。大型项目最直接的就是上库... 更方便,更不容易出错。 但其实小项目就没什么必要了。东西比较多,这里不再阐述它们的实现和做了什么。

关于“如何解决React中组件通信问题”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

另外有需要云服务器可以了解下创新互联建站www.cdcxhl.com,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。


网站栏目:如何解决React中组件通信问题-创新互联
标题链接:http://ybzwz.com/article/gseoc.html

其他资讯