Knockout.js:在可选定义的值上计算可观察性
Knockout.js: computed observables on optionally defined values
我为Yesod(一个Haskell web框架)编写了一个整洁的小knockout.js绑定,但在处理可选定义的值时遇到了一些问题。绑定的Haskell部分旨在提供一个javascript片段,该片段对同一处理程序进行Ajax调用,并接收通过ko.mapping解析的JSON对象。
这一切都很好,但我在处理可选值时遇到了问题。如果我用一个可选的记录提供一个值,JSON发射器会将其视为可选的,并且不发射它
例如,请求的JSON响应
data Foo = Foo { bar :: Maybe Int
, baz :: Int
}
serveThis :: Foo
serveThis = Foo (Nothing) 0
是{baz:"0"}
我理解为什么会这样,我可以改变它(但如果可能的话,我宁愿不改变)。问题是,当我在serveThis的JSON表示上调用ko.mapping.fromJS时,bar字段不会变成可观察的。好吧,我也明白。我可以使用with绑定来进行条件数据绑定。但我不知道足够的JavaScript来有条件地定义计算的可观察性。
我的真实代码看起来像:
var ViewModel = function (data) {
ko.mapping.fromJS(data, {}, this);
this.notes.stdDev.percent = ko.computed( function () {
return numeral( this.notes.stdDev() ).format("0%");
}, this);
}
因此,如果标准偏差没有在Haskell端定义,它就不会作为JSON字段发出,因此ko.mapping不会使其成为可观察的。那么,我如何有条件地定义百分比表示呢?
在省略stdDev
属性的实例中,视图模型也会省略该属性,这是合适的行为吗?或者,无论初始值如何,您的视图模型是否需要包含属性的相关可观察对象?
如果是前者,那么你只需要包括一些类似于以下的简单条件逻辑:
this.notes.stdDev.percent = ko.computed(function() {
return this.notes.stdDev ? this.notes.stdDev * 100 + "%' : 'n/a';
}, this);
这将检查是否存在stdDev
属性,并在未定义该属性时返回静态值'n/a'
。
但是,如果您的视图需要所有用户输入stdDev值,即使省略了初始值,我也不建议使用此模型。相反,你可能想考虑放弃ko.mapping。大约一年前,我广泛使用了ko.mappiing,但最近我很少使用它,因为我使用JS模型得到了更好的结果。这里有一个视图模型体系结构的例子,它最近一直在为我工作。
var viewModel = (function () {
return { init: init };
function init(data) {
var self = {
notes: ko.observable()
};
self.notes(new Notes(data));
ko.applyBindings(self);
return self;
}
function Notes(data) {
return {
stdDev: ko.observable(data.notes),
otherProp: ko.observable(data.otherProp),
}
}
}());
至少在映射讨论的上下文中,需要注意的主要内容是Notes
构造函数。虽然可能会复制从服务层返回的模型,但与映射解决方案相比,这种模式允许可靠的数据结构。在决定它不适用于所有情况之前,我与映射进行了长达6个月的斗争,这种明确的模型定义确实为视图模型增加了清晰度和可靠性。尽管映射可以简化管道代码,但它确实对传入数据的结构产生了不必要的依赖。事实仍然是,如果视图引用了视图模型中不存在的属性,则视图将崩溃。
如果您确实想避免在两个层之间复制模型,那么有一个折衷的解决方案,您可以为所依赖的属性定义默认值,并在缺少默认值时使用默认值扩展传入数据模型。jQuery的扩展函数适用于这个函数——如果您已经依赖jQuery的话。例如:
var noteDefaults = {
stdDev: 0
};
var input = $.extend({}, defaults, data);
ko.mapping.fromJS(input, {}, this);
希望这能有所帮助!
- 如何收集Knockout可观察性以放入JSON
- 在隐藏值上调用 jQuery .trigger('change') 会破坏与 KNOCKOUT 相关的可观察性
- Knockout.js性能-有多少可观察性
- 挖空映射:加载数据后,父模型中的计算可观察量不会更新
- Knockout.js:在可选定义的值上计算可观察性
- 如何使用ES6在Ember中声明可观察性或计算属性
- 如何使某些可观察的“独立”计算可观察(Knockout.js)
- 如何在运行时向计算可观察量添加其他数组项
- 在不重置对象的情况下重新计算计算可观察量
- RXJS5 - 按每个对象包含的可观察性过滤对象数组
- .replace() 表达式未在计算可观察量中更新
- 对计算可观察量的挖空 JS 绑定不起作用
- Angular2 Http 请求返回没有映射方法的可观察性
- 如何将计算可观察量添加到 KNOCKOUTJS 映射中
- 未执行计算可观察量
- 当可观察数组项的属性更改时,计算可观察量不会更改
- 在knockoutjs中计算的可观察性;更改时不更新
- 如何通过多个$.ajax调用实现异步计算可观察性
- knockoutjs:计算级联数组(复杂视图模型)中的可观察性和this指针
- 使用计算的可观察性的对象范围