模型助手在 React/Flux 中属于哪里?
Posted
技术标签:
【中文标题】模型助手在 React/Flux 中属于哪里?【英文标题】:Where do model helpers belong in React/Flux? 【发布时间】:2015-12-20 00:30:14 【问题描述】:在尝试围绕 React 和 Flux 进行思考时,我很难决定将我称之为“模型助手”的方法放在哪里有意义。
例如,假设 Store 中包含一个“Person”实体,并且假设这个 Person 有一个“名字”和一个“姓氏”,那么在哪里放置“完整name" 简单地将两者连接在一起的辅助方法?我的直觉说最好在商店中使用“全名”,但不确定。如果是这样,它会是一个 Action 更新 store 中的这个值,还是应该在 Store 本身内计算?
有没有一个可以接受的地方来放置这种功能?
谢谢!
【问题讨论】:
【参考方案1】:为了保持事情的可管理性,特别是如果你有很多商店和一个大的组件树,试着集中你的商店和组件的功能:
-
存储用于 a) 存储数据(名字、姓氏,非派生数据),以及 b) 为组件提供数据(包括派生数据)。
组件用于向用户呈现 a) 数据,以及 b) 与数据交互的锚。
我会尽量避免在组件树中操作数据。并建议任何组件中的任何数据道具始终来自商店。它们是从更高的组件传下来的,但不会在此过程中被操纵。
如果辅助函数只处理数据(例如计算组中的总人数),请将它们放在存储中。 如果他们处理表示逻辑(例如页面上第一人称的字体大小应该更大),请将它们放在单独的位置。我将它们放在单独的实用程序中进行导入。 但仅在可能的最低组件处调用这些函数。
这样,您的代码更易于维护。
数据助手和表示逻辑之间有很多灰色区域,所以在这种情况下你的选择很难说。但只要您始终如一地应用自己的逻辑,您的代码就会保持可管理性。
这样,当一个组件给你问题时,更容易追踪 props 的来源,或者你的组件中应用于这些 props 的函数代码。
所以也许是一个具有全名函数的高阶组件,但我不会让高阶组件创建一个新的道具。
【讨论】:
【参考方案2】:所以 store 保存了应用程序的数据和业务逻辑,我看到这个帮助器就像一个应该在你的 store 中发生的操作。您不需要更新全名的操作,一旦第一个和第二个名称可用,它应该由商店本身连接。
【讨论】:
【参考方案3】:除了@Christian 的回答(我同意)之外,您还可以通过使用object-assign
模块在商店中使用通用助手:https://www.npmjs.com/package/object-assign
这是我的一个商店的部分示例,它带有辅助方法(例如isAuthenticated
和getUsername
),使用object-assign
将StatusMixin
组合到每个商店中:
var AuthStore = assign(, StatusMixin, EventEmitter.prototype,
isAuthenticated: function ()
return _data.get(TOKEN_KEY) ? true : false;
,
getUsername()
return _data.get(USERNAME_KEY);
,
getToken()
return _data.get(TOKEN_KEY);
,
invalidate()
_data = _data.clear();
this.setStatus(''); //this method is from the StatusMixin!
this.emitChange(Constants.CHANGED);
,
emitChange: function()
LocalStorage.set(Constants.ls.AUTH_STORE,
auth_token: _data.get(TOKEN_KEY),
username: _data.get(USERNAME_KEY)
);
this.emit(Constants.CHANGED);
,
addChangeListener: function(callback)
this.on(Constants.CHANGED, callback);
,
removeChangeListener: function(callback)
this.removeListener(Constants.CHANGED, callback);
,
getState: function()
return _data;
);
和(完整的)StatusMixin
'use strict';
var logger = require('../../util/Logger');
var StatusMixin =
_status: '',
getStatus: function()
return this._status;
,
setStatus(status)
this._status = status;
;
module.exports = StatusMixin;
现在我可以调用 AuthStore.setStatus(Constants.request.PENDING);
(我为每个 Store 调用),而无需在每个 Store 上编写 setStatus
方法。
【讨论】:
【参考方案4】:通常,这里的“最佳实践”是创建一个高阶组件,该组件提供辅助函数或串联全名作为需要此修改值的组件的道具。
function giveFullName(Component)
const ComponentWithFullName = React.createClass(
render()
return <Component ...this.props fullName=this.props.firstName+" "+this.props.lastName />;
);
return ComponentWithFullName;
;
var PersonPage = React.createClass(
render()
var name = this.props.fullName; // get fullName from props
return <div>'Hello '+(name ? name : 'Mystery Stranger')</div>;
);
PersonPage = ComponentWithFullName(PersonPage)
);
我不同意 @cristian 的回答,因为 ReactJS 的优势之一是它的关注点分离度很高,并且易于推理应用程序信息流。如果我们在 store 中放置一个 helper 方法,那么我们不知道什么时候看到全名,是来自 store 的全名,还是一个组件通过连接来自同一个 store 的名字和姓氏自己创建的全名.但是,如果不把这个全名函数放在 store 中,那么我们就知道任何全名都来自一个组件。创建一个可以提供此功能的高阶组件可以实现相同的 DRY 原则,同时保持清晰推理值/UI 元素来自何处的能力。
请参阅https://medium.com/@dan_abramov/mixins-are-dead-long-live-higher-order-components-94a0d2f9e750,了解有关 React 中的 HoC 与 Mixins 的更多信息,以及为什么您应该偏爱 HoC。
【讨论】:
以上是关于模型助手在 React/Flux 中属于哪里?的主要内容,如果未能解决你的问题,请参考以下文章