当React Flux商店发出多种事件时,这是一个好的设计吗?

时间:2015-06-27 13:15:38

标签: reactjs reactjs-flux

我发现的几乎所有关于flux的教程每个商店只发出一个事件(emitChange)。我真的不知道,这是故意的,或仅仅是教程简单的结果。

我尝试实现一个与CRUD架构相对应的商店,我想知道为每个CRUD方法发出不同事件是否是一个好的设计决策。

我的一家商店的相关部分如下所示:

var UserStore = _.extend({}, EventEmitter.prototype, {

    emitChange: function() {
        this.emit('change');
    },

    emitUserAdded: function() {
        this.emit('userAdded');
    },

    emitUserUpdated: function() {
        this.emit('userUpdated');
    },

    emitUserDeleted: function() {
        this.emit('userDeleted');
    },

    // addListener, removeListener in the same manner
});

如果我的方法有误,我怎么告诉我的组件发生的事件类型(例如:删除或更新)

2 个答案:

答案 0 :(得分:12)

作为设计模式的Flux建立在所有数据都驻留在“商店”的想法之上。每个商店都保存给定信息域的数据。例如:在Flux中,所有注释都将驻留在CommentStore中。

当在商店中更改数据时,它应该发出一个事件,并且构建在此“信息域”之上的所有组件应该重新呈现并显示新的域数据。

我发现当商店发出多种事件类型时,组件更有可能不会侦听该特定事件,因此在域数据被更改时不会重新渲染。

这打破了整个通量模式,并且很容易创建很难找到组件与商店信息不同步的错误。

我建议您根据“Demeter法则”设计组件 - 每个组件应该只知道它需要的数量。

因此,您应该创建一个侦听单个商店事件的commentListComponent,而不是侦听“commentList已更新”的事件的组件。因此,组件将侦听commentStore.on('change') - 我通常会让所有商店发出'change'事件。当商店发出时,您应该重新渲染commenListComponent中的数据以反映商店。如果使用React,则使用setState。

var commentStore = _.extend({}, EventEmitter.prototype, {

updateComents: function() {
    // Update comments and emit
    this.emit('change');
},

removeComments: function() {
    // Remove comments and emit
    this.emit('change');
},

getState: function() {
    return {
        comments: this.comments,
        someOtherDomainData: this.meta,
    }
}
});

//commentListComponent.js
var commentListComponent = React.createClass({
    componentDidMount : function() {
        commentStore.on('change', this._commentChanged);
    },
    componentWillUnmount : function() {
        commentStore.off('change', this._commentChanged);
    },
    _commentChanged : function() { 
        this.setState({ comments : commentStore.getState().comments });
    },
    render : function() {
        var comments = // Build a list of comments.
        return <div>{comments}</div>
    }
})

这使得数据流更加简单,并且避免了很难发现错误。

答案 1 :(得分:0)

我的用例迫使我使用不同的事件。我有一个显示许多复杂对象的地图组件,刷新每个对象都非常昂贵。

EventEmitter2实现了多级别和通配符事件。它允许我听“改变”事件,或更具体地说是子级事件“change.add”“change.remove”...

this.emit("change.add");

可以通过

收听
myStore.on('change.*', callback);
myStore.on('change.add', callback);

通过这种方式,我的许多组件都可以简单地收听“change。*”事件。需要优化的更复杂的组件可以监听特定的事件。

两全其美

PS:别忘了启用通配符。参见文档