Javascript KnockoutJS:阻止特定属性设置脏标志

Javascript KnockoutJS:阻止特定属性设置脏标志,javascript,knockout.js,knockout-mapping-plugin,Javascript,Knockout.js,Knockout Mapping Plugin,在StackOverflow社区的帮助下,基于以下示例,我能够使脏标志实现正常工作: 它正是我想要的,除了一个我不知道如何解决的用例 基本上,我有一个从数据库自动填充的选择菜单。这个选择菜单还有一个选项,可以对我的后端进行Ajax调用,刷新选项列表,更新数据库并返回结果。这就是我感到毛骨悚然的地方 第一种方法工作正常,但是,它必须重新索引并重新应用我的整个viewModel,大约需要2-3秒,在一台本地机器上运行,有16G的ram和SSD jsondata.component.available

在StackOverflow社区的帮助下,基于以下示例,我能够使脏标志实现正常工作:

它正是我想要的,除了一个我不知道如何解决的用例

基本上,我有一个从数据库自动填充的选择菜单。这个选择菜单还有一个选项,可以对我的后端进行Ajax调用,刷新选项列表,更新数据库并返回
结果。这就是我感到毛骨悚然的地方

第一种方法工作正常,但是,它必须重新索引并重新应用我的整个
viewModel
,大约需要2-3秒,在一台本地机器上运行,有16G的ram和SSD

jsondata.component.available_tags = result.available_tags;
ko.mapping.fromJS(jsondata, viewModel);
第二种方法也可以工作,而且几乎是即时的,但是,它设置了
isDirty()
标志,这是我想要避免的,因为这些数据已经来自数据库,我不需要保存它。我也不能使用
isDirty.reset()
方法,因为如果在我单击菜单选项更新
可用标记之前,
isDirty
被其他设置,它也会重置。我也希望避免这种情况

viewModel().component.available_tags(result.available_tags);
我的问题是:使用第一种方法,我可以在特定元素而不是整个数据集上使用
ko.mapping.fromJS()
强制UI刷新吗?或者,使用第二种方法,我可以避免在更新
可用标记时设置
isDirty
标志吗?问题是,我仍然需要将
可用的\u标记作为可观察的标记,因此选择菜单会自动生成/更新

更新:我能够用

ko.mapping.fromJS(result.available_tags, {}, viewModel().component.available_tags);

但这立刻引起了isDirty旗。。。Argh

除了Tomalak的建议之外(我完全同意),也许toJSON方法可以帮助您解决类似情况下不希望分割模型的问题。如果您的脏标志实现使用ko.toJSON作为散列函数,如Ryan Niemeyer所做的那样,您可以为您的模型(脏标志在其上处于活动状态)提供一个toJSON方法,您可以执行如下操作:

function MyObjectConstructor() {
    this.someProperty = ko.observable();
    this.somePropertyNotUsedInDirtyFlag = ko.observable();
}
MyObjectConstructor.prototype.toJSON = function () {
    var result = ko.toJS(this);
    delete result.somePropertyNotUsedInDirtyFlag;
    return result;
};

请注意,这也用于在其他一些情况下序列化对象,例如ajax调用。它通常是一个方便的函数,用于在不同的上下文中使用对象之前从对象中删除计算对象等。

我认为解决方案的关键是1)不要将整个视图模型基于单个
ko.mapping.fromJS()
,2)使用映射选项,特别是为了避免不必要地重建实际上没有改变的东西,以及3)将视图模型分为两部分:与脏标志没有连接的“操作”部分和带有脏标志的“用户数据”部分。当我第一次开始集成ko.mapping时,我的性能受到了巨大的影响,事实证明,为了节省内存,我需要非常有选择性地选择将哪些属性转换为可观察属性。@Tomalak:虽然这并不是一个解决方案,但它对我帮助很大。我从我的
viewModel
中去掉了很多绒毛,并将
isDirty()
标记直接附加到我关心的仅有的两个属性上,而不是它们的父属性上。请把它作为一个答案提交,这样我就可以把它解决了。谢谢你的帮助。嘿,既然你最终完成了所有的工作(还有“好”和“坏”的代码示例!),为什么你不以优异的成绩写出一个很好的答案,列出问题和解决方案呢?我所做的只是推你一下。我会在你身边投票支持你(如果我看到可以改进的代码,也可以给出更多提示)。