通过反应发出和处理全球事件

Tho*_*ggi 19 javascript reactjs reactjs-flux

我正在玩一些反应来建立一个"添加到购物车按钮".这是我的代码.

var ProductPurchase = React.createClass({
  handleSubmit: function(e){
    e.preventDefault();
    $.ajax({
      url: "/cart/add.js",
      method: "post",
      dataType: "json",
      data: {
        "id": this.props.variantId,
        "quantity": this.props.quantity,
      },
      success: function(data) {
        // emit cart added event
      }.bind(this),
      error: function(xhr, status, err) {
        // emit error event (cart added)
      }.bind(this)
    });
  },
  getDefaultProps: function(){
    return {
      quantity: 1,
      variantId: 231634908,
      buttonText: "Add to cart"
    }
  },
  render: function() {
    return (
      <div className="productPurchase">
        <form action="/cart/add" method="post" enctype="multipart/form-data" onSubmit={this.handleSubmit}>
          <input type="hidden" name="quantity" value={ this.props.quantity } />
          <input type="hidden" name="id" value={ this.props.variantId } />
          <button type="submit">{this.props.buttonText}</button>
        </form>
      </div>
    );
  }
});
Run Code Online (Sandbox Code Playgroud)

我很好奇的是这个ajax处理程序.我非常确定反应的重点是组件之间的互操作性,除了我不知道在哪里引导这些事件.我可以想象一些不同的组件,如购物车计数指示器,如果成功或错误提醒,如果失败,但我不知道如何利用这些.这是助焊剂调度员的全部意义吗?

Mic*_*art 17

是的,这肯定是Flux调度员的一部分 - 或者您想要使用的任何事件发射器.

你走这条路,虽然之前,它很容易,只是向下传递的事件处理程序作为道具,而不使用助焊剂或自定义事件的发射器-就像你用onSubmit,onClick等处理程序正常的DOM元素.然后让父母处理设置状态,并可能将其传达给其他孩子(通过道具).

所以在这种情况下,想象一下处理事件的父组件:

var RootComponent = React.createClass({
  handleCartAdded: function(cart) {
    console.log('Got a new cart: ' + cart);
  }
  handleError: function(err) {
    console.error(err)
  }
  render: function() {
    return (
      <ProductPurchase onCartAdded={this.handleCartAdded} onError={this.handleError} />
    )
  }
})
Run Code Online (Sandbox Code Playgroud)

然后ProductPurchase组件的相关部分将是:

  success: function(data) {
    this.props.onCartAdded(data)
  }.bind(this),
  error: function(xhr, status, err) {
    this.props.onError(err)
  }.bind(this)
Run Code Online (Sandbox Code Playgroud)

一个更复杂的例子是将结果传递给另一个子组件 - 但是,再次将其留给父组件来管理它:

var RootComponent = React.createClass({
  handleCartAdded: function(cart) {
    this.setState({cart: cart})
  }
  handleError: function(err) {
    console.error(err)
  }
  render: function() {
    return (
      <div>
        <ProductPurchase onCartAdded={this.handleCartAdded} onError={this.handleError} />
        <CartSummary cart={this.state.cart} />
      </div>
    )
  }
})
Run Code Online (Sandbox Code Playgroud)

这样,组件就会相互分离 - 而数据/函数只能通过明确的契约(props)传递.

这种简单的事件处理方式更明确,更容易调试 - 所以如果你的应用程序变得非常复杂和/或你有很多组件需要与每个组件进行通信,我真的只会求助于Flux风格的架构其他以复杂的方式.


San*_*ahu 5

Flux用于解耦编程结构(包括AJAX调用).

这是Flux Docs的图表

Flux架构图

Flux架构中的调度程序始终保持在全局范围内.因此,调度程序涉及的任何操作始终发生在全局范围内.此外,调度程序和事件系统略有不同,事件系统始终注册绑定到特定事件的回调,但在调度程序的情况下,所有回调都绑定到所有事件.

如何使用Dispatcher?(不使用Stores和ActionCreators的简化方法)

  1. 如果应用程序的其他部分受到此AJAX调用的影响,那么您不应该从此组件进行此AJAX调用,而是将AJAX调用移动到新文件和函数中.例如,使用CommonJS,

    // CartApiUtils.js
    module.exports = {
        addToCart: function(item){
            // AJAX call
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 使用Flux的Dispatcher类创建AppDispatcher(在整个应用程序中很常见)

    var appDispatcher = new Dispatcher();
    
    Run Code Online (Sandbox Code Playgroud)
  3. 在addToCart()函数中,在成功的AJAX响应中,使用AppDispatcher调度事件:

    appDispatcher.dispatch({
        actionType: 'cart.newItemAdded',
        data: dataFromAjax
    });
    
    Run Code Online (Sandbox Code Playgroud)
  4. 在您的应用程序中,无论您想在何处使用此事件,都可以向调度程序注册一个函数.

    appDispatcher.register(function(payload){
        if(payload.actionType === 'cart.newItemAdded'){
            // payload.data contains the data
        }
    });
    
    Run Code Online (Sandbox Code Playgroud)

这是一种简化的方法.在更规范化的结构和更大的应用程序中,您应该使用Stores(类似于MVC的Model层,但不完全相同)和ActionCreator,其中视图层上的任何交互都是用户的操作以及AJAX调用的任何响应也成为服务器的一个动作.

Thumb规则是,必须从商店填充(或更新)视图,并且必须在Dispatcher事件上更新商店.

  • 注意:请勿使用您在组件中链接的调度程序,因为它无法取消注册,这意味着无法在componentWillUnmount中进行清理.如果您希望在没有商店的情况下使用它,只需使用普通事件发射器(例如节点中的events.EventEmitter). (2认同)