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

gsa*_*nta 17 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
});
Run Code Online (Sandbox Code Playgroud)

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

Sil*_*rom 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>
    }
})
Run Code Online (Sandbox Code Playgroud)

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

  • 好的,我看到CommentList组件不必知道这一点.但想象一下弹出组件,它通知用户删除成功(将其命名为CommentPopup).所以这个组件需要一些事件,告诉它,删除发生了,你将如何解决它? (9认同)
  • 你不应该.这才是重点.让商店处理所有逻辑,让组件只呈现商店返回的状态.一个呈现列表中所有注释的组件不需要知道注释是否被删除,它只需要用所有注释重新呈现自己. (2认同)
  • TeChn4K - 这取决于您的具体设置.正如你所说,刷新是昂贵的,特别是刷新DOM时.Flux从来没有建立在一切都应该被重新渲染的想法上 - 只是看起来应该从程序员的角度重新渲染一切.因此,Flux在使用虚拟dom的环境中蓬勃发展.这是因为虚拟dom(react,vue等)最大限度地减少了必要的重新渲染次数.如果虚拟dom无法开箱即用,那么通常可以在适合刷新数据时提示框架. (2认同)