react.js用于与父节点通信的自定义事件

时间:2014-02-22 08:23:26

标签: reactjs

我正在制作和监听正常的DOM CustomEvent以与父节点进行通信:

在孩子:

  var moveEvent = new CustomEvent('the-graph-group-move', { 
    detail: {
      nodes: this.props.nodes,
      x: deltaX,
      y: deltaY
    },
    bubbles: true
  });
  this.getDOMNode().dispatchEvent(moveEvent);

在父母:

componentDidMount: function () {
  this.getDOMNode().addEventListener("the-graph-group-move", this.moveGroup);
},

这样可行,但是有一种特定于React的方式会更好吗?

6 个答案:

答案 0 :(得分:36)

如上所述:

  

React方法是通过props显式地将回调传递给子节点 - 。在React中不支持冒泡的自定义事件。

反应式编程抽象是正交的:

  

通过观察者模式编程交互系统很难且容易出错,但仍然是许多生产环境中的实现标准。我们提出了一种逐步弃用观察者以支持反应式编程抽象的方法。多个库层帮助程序员顺利地将现有代码从回调迁移到更具声明性的编程模型。

React哲学基于Command模式:

enter image description here

<强>参考

答案 1 :(得分:3)

我发现还有另外一个非常合理,特别是如果从父母到孩子的钻洞已经变得很麻烦了。他称之为不太简单的沟通。这是链接:

https://github.com/ryanflorence/react-training/blob/gh-pages/lessons/04-less-simple-communication.md

答案 2 :(得分:3)

你可以编写一个简单的服务,然后使用它

/** eventsService */
module.exports = {
  callbacks: {},

  /**
   * @param {string} eventName
   * @param {*} data
   */
  triggerEvent(eventName, data = null) {
    if (this.callbacks[eventName]) {
      Object.keys(this.callbacks[eventName]).forEach((id) => {
        this.callbacks[eventName][id](data);
      });
    }
  },

  /**
   * @param {string} eventName name of event
   * @param {string} id callback identifier
   * @param {Function} callback
   */
  listenEvent(eventName, id, callback) {
    this.callbacks[eventName][id] = callback;
  },

  /**
   * @param {string} eventName name of event
   * @param {string} id callback identifier
   */
  unlistenEvent(eventName, id) {
    delete this.callbacks[eventName][id];
  },
};

示例(触发相同)

import eventsService from '../../../../services/events';
export default class FooterMenu extends Component {
  componentWillMount() {
    eventsService
      .listenEvent('cart', 'footer', this.cartUpdatedListener.bind(this));
  }

  componentWillUnmount() {
    eventsService
      .unlistenEvent('cart', 'footer');
  }

  cartUpdatedListener() {
    console.log('cart updated');
  }
}

答案 3 :(得分:1)

一种可能的解决方案,如果您绝对必须诉诸ReactJs应用程序中的Observer模式,您可以劫持正常事件。例如,如果您希望删除键导致标记为删除的<div>,则可以让<div>侦听将由customEvent调用的keydown事件。捕获正文上的keydown并在选定的customEvent上发送<div> keydown事件。分享,以防有人帮助。

答案 4 :(得分:1)

您可以通过上下文向下传递的回调来冒泡事件:[CodePen]

import React, {Component, PropTypes} from 'react';

class EventContext extends Component {
  static contextTypes = {
    onMyEvent: PropTypes.func
  };
  static childContextTypes = {
    onMyEvent: PropTypes.func.isRequired
  };
  static propTypes = {
    onMyEvent: PropTypes.func.isRequired
  };
  getChildContext() {
    let {onMyEvent} = this.props;
    return {
      onMyEvent: (...args) => {
        // stop propagation if handler returns false
        if (onMyEvent(...args) !== false) {
          // bubble the event
          this.context.onMyEvent && this.context.onMyEvent(...args);
        }
      }
    };
  }
  render() {
    return this.props.children;
  }
}

class MyComponent extends Component {
  static contextTypes = {
    onMyEvent: PropTypes.func
  };
  render() {
    let {onMyEvent} = this.context;
    return <button onClick={onMyEvent}>Click me</button>;
  }
}

export default <EventContext onMyEvent={e => console.log('grandparent got event: ', e)}>
  <EventContext onMyEvent={e => console.log('parent got event: ', e)}>
    <MyComponent/>
  </EventContext>
</EventContext>;

答案 5 :(得分:0)

我知道到现在这个问题已经很老了,但是这个答案可能仍然可以帮助某个人。我为React写了一个JSX杂注,其中添加了声明式自定义事件:jsx-native-events

基本上,您只是使用onEvent<EventName>模式来监视事件。

<some-custom-element onEventSomeEvent={ callback }></some-custom-element>