Javascript 使用 react 发出和处理全局事件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27470817/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Emitting and handling global events with react
提问by ThomasReggi
I'm playing around a bit with react to build an "Add to cart button". Here's my code.
我正在尝试使用 react 来构建“添加到购物车按钮”。这是我的代码。
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>
);
}
});
What I'm curious about is this ajax handler. I'm pretty sure the whole point of react is interoperability between components, except I don't know where to lead these events off to. I could imagine a couple of different components like a cart count indicator if success or a error alert if failure but I don't exactly know how to tap into these. Is this the whole point of flux's dispatchers?
我很好奇的是这个 ajax 处理程序。我很确定 React 的重点是组件之间的互操作性,除了我不知道将这些事件引向何处。我可以想象几个不同的组件,比如成功时的购物车计数指示器或失败时的错误警报,但我不完全知道如何利用这些。这就是Flux 调度员的全部意义所在吗?
采纳答案by Michael Hart
Yes, it's certainly part of the point of Flux's dispatchers – or any event emitter that you wanted to use.
是的,这当然是 Flux 的调度程序的一部分——或者你想使用的任何事件发射器。
Before you go down that path though, it's very easy to just pass down event handlers as props without using Flux or custom event emitters – just as you would with onSubmit, onClick, etc handlers for normal DOM elements. Then have the parent deal with setting the state, and potentially communicating that to other children (via props).
在你走这条路,虽然,它很容易,只是向下传递的事件处理程序作为道具,而不使用助焊剂或自定义事件的发射器-就像你用onSubmit,onClick等处理程序正常的DOM元素。然后让父母处理设置状态,并可能将其传达给其他孩子(通过道具)。
So in this case, imagine a parent component that deals with the events:
所以在这种情况下,想象一个处理事件的父组件:
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} />
)
}
})
And then the relevant part of your ProductPurchasecomponent would be:
然后ProductPurchase组件的相关部分将是:
success: function(data) {
this.props.onCartAdded(data)
}.bind(this),
error: function(xhr, status, err) {
this.props.onError(err)
}.bind(this)
A more complex example would be to pass the result to another child component – but again, leave it up to the parent to manage this:
一个更复杂的例子是将结果传递给另一个子组件——但同样,让父组件来管理它:
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>
)
}
})
This way, the components are decoupled from each other – and data/functions can only be passed in by a clear contract (props).
通过这种方式,组件彼此解耦——数据/函数只能通过明确的合约(道具)传入。
This simple style of event handling is a lot more explicit and easier to debug – so I would really only resort to a Flux style architecture if your app is getting really complex and/or you have a lot of components that all need to communicate with each other in a complex manner.
这种简单的事件处理风格更加明确且易于调试——因此,如果您的应用程序变得非常复杂和/或您有很多组件都需要与每个组件进行通信,我真的只会求助于 Flux 风格的架构其他以复杂的方式。
回答by Sanket Sahu
Flux is used to decouple programming constructs (including AJAX calls).
Flux 用于解耦编程结构(包括 AJAX 调用)。
Here is the diagram from the Flux Docs
这是Flux Docs 中的图表


Dispatcherin Flux architecture always remains in Global scope. So any operation involved with the dispatcher always occurs in the global scope. Also, dispatcher and event-system has a slight difference, event system always registers callbacks bound to a specific event but in case of dispatchers, all the callbacks are bound to all the events.
Flux 架构中的Dispatcher始终保持在全局范围内。所以任何涉及调度程序的操作总是发生在全局范围内。此外,调度程序和事件系统略有不同,事件系统总是注册绑定到特定事件的回调,但在调度程序的情况下,所有回调都绑定到所有事件。
How to use Dispatcher? (Simplified approach without the use of Stores and ActionCreators)
如何使用调度器?(不使用 Stores 和 ActionCreators 的简化方法)
If other parts of application is affected by this AJAX call then you shouldn't make this AJAX call from this component, rather move the AJAX call into a new file and a function. Eg using CommonJS,
// CartApiUtils.js module.exports = { addToCart: function(item){ // AJAX call } }Create an AppDispatcher (which is common throughout the application) using Flux's Dispatcher class
var appDispatcher = new Dispatcher();In addToCart() function, on successful AJAX response, dispatch an event using AppDispatcher:
appDispatcher.dispatch({ actionType: 'cart.newItemAdded', data: dataFromAjax });In your app, wherever you want to use this event, you can just register a function to dispacher.
appDispatcher.register(function(payload){ if(payload.actionType === 'cart.newItemAdded'){ // payload.data contains the data } });
如果应用程序的其他部分受到此 AJAX 调用的影响,则不应从该组件进行此 AJAX 调用,而应将 AJAX 调用移动到新文件和函数中。例如使用 CommonJS,
// CartApiUtils.js module.exports = { addToCart: function(item){ // AJAX call } }使用 Flux 的Dispatcher 类创建一个 AppDispatcher(在整个应用程序中很常见)
var appDispatcher = new Dispatcher();在 addToCart() 函数中,在成功的 AJAX 响应中,使用 AppDispatcher 调度事件:
appDispatcher.dispatch({ actionType: 'cart.newItemAdded', data: dataFromAjax });在您的应用程序中,无论您想在何处使用此事件,您只需向调度程序注册一个函数即可。
appDispatcher.register(function(payload){ if(payload.actionType === 'cart.newItemAdded'){ // payload.data contains the data } });
This is a simplified approach. In a more normalized structure and larger app, you should use Stores (which is something like the Model layer of MVC, but not identical) and ActionCreator where any interaction on the view layer is an action by the user and any response by the AJAX call also becomes an action from the Server.
这是一种简化的方法。在更规范化的结构和更大的应用程序中,您应该使用 Stores(类似于 MVC 的模型层,但不完全相同)和 ActionCreator,其中视图层上的任何交互都是用户的操作和 AJAX 调用的任何响应也成为服务器的一个动作。
Thumb rule is that, Views must be populated (or updated) from Stores and Stores must be updated on Dispatcher events.
Thumb 规则是,必须从 Stores 填充(或更新)视图,并且必须在 Dispatcher 事件上更新 Stores。
回答by C.L.
What about using npm's "react-global-events" ?
使用 npm 的“ react-global-events”怎么样?

