我习惯于计算Ember Object Model中的属性。这是一种指定依赖于其他属性的计算属性的便捷方式。
说fullName
取决于firstName
和lastName
,我可以将计算属性设置为函数computeProperties
,并在每次进行更改时调用computeProperties
。
示例:
function computeFullName(state) {
const fullName = state.get('firstName') + state.get('lastName');
const nextState = state.set('fullName', fullName);
return nextState;
}
function computeProperties(state) {
const nextState = computeFullName(state);
return nextState;
}
// store action handler
[handleActionX](state) {
let nextState = state.set('firstName', 'John');
nextState = state.set('lastName', 'Doe');
nextState = computeProperties(nextState);
return nextState;
}
有没有办法自动设置计算属性,这样我就不必每次都调用额外的函数。在Redux或ImmutableJS。
答案 0 :(得分:11)
Redux作者在这里!
Using reselect as suggested by WildService是要走的路。我认为我们不会将其纳入核心,因为重新选择可以很好地完成工作,我们可以将它作为一个单独的库。
我想注意几件事:
即使重新选择,您也不想在减速机内计算数据。选择器应该在上运行由reducers管理的状态。换句话说,选择器是Redux存储状态和组件之间的一步 - 它们不在Reducer中。必须保持Redux状态规范化,以便于更新。< / p>
我们实际上鼓励您将与相关的缩减器一起定义,以便当您更改状态时,您不必更改组件强> - 他们会使用选择器。您可以在Redux folder of Flux Comparison
我们有documentation page introducing reselect and describing how to use it for computing derived data。看看吧。
答案 1 :(得分:4)
结帐reselect。可组合的纯函数,用于高效计算来自商店的派生数据。 Afaik有计划在某些阶段将重选的选择器推向Redux核心,如果它们被证明是受欢迎的话。还有一个在自述文件底部使用ImmutableJS的例子。
答案 2 :(得分:1)
要创建计算属性,您可以使用独立的可观察库mobservable。
var user = mobservable.props({
firstName: 'John',
lastName: 'Doe',
fullName: function() {
return this.firstName + this.lastName
}
});
var nameViewer = mobservable.ObservingComponent(React.createClass({
render: function() {
return (<span>{user.fullName}</span>)
}
});
这应该是它的要点,现在对user.firstName或lastName的任何更改都会重新呈现你的nameViewer组件。您可以进一步将此与fluxx之类的flux实现相结合来更改数据,并通过组件树推送用户自己。但请注意,用户对象本身不不可变(在这种情况下,它毕竟不会被观察到;-))另请参阅此trivial和slightly more interesting小提琴举个例子。
答案 3 :(得分:0)
这样的事情怎么样?
export const getWidgetsWithComputedProps = widgets => {
return widgets.map(w => getWidgetWithComputedProps(w));
};
export const selectWidgetType = widget => {
switch (widget.type) {
case 'line':
return 'time-series';
case 'pie':
case 'bar':
return 'cross-sectional';
default:
console.warn('Back up: that type of widget does not exist!', widget.type);
return null;
}
};
export const getWidgetWithComputedProps = createSelector(
widget => widget,
selectWidgetType,
(widget, _type) => {
return {...widget, _type}
}
);