Knockout.js 更改不同的可观察对象时更新可观察数组属性

Knockout.js 更改不同的可观察对象时更新可观察数组属性,knockout.js,Knockout.js,我有一个可以观察到的“locale”,它基本上只是一个包含特定于locale的字符串的JS对象。我还有一个tabs observable数组,它包含多个属性,其中一个属性是由区域设置值填充的标题 e、 g 下面是一个要演示的JSFIDLE: 我正试图找出最好的策略,当可观察的区域设置发生变化时,使选项卡标题发生变化 我尝试过使用敲除映射,但这似乎没有帮助。我还尝试添加一个ko.observearray.fn.refresh来更新选项卡数组中的数据,但它只是使用原始选项卡数据,而不是引用回区域设置

我有一个可以观察到的“locale”,它基本上只是一个包含特定于locale的字符串的JS对象。我还有一个tabs observable数组,它包含多个属性,其中一个属性是由区域设置值填充的标题

e、 g

下面是一个要演示的JSFIDLE:

我正试图找出最好的策略,当可观察的区域设置发生变化时,使选项卡标题发生变化


我尝试过使用敲除映射,但这似乎没有帮助。我还尝试添加一个ko.observearray.fn.refresh来更新选项卡数组中的数据,但它只是使用原始选项卡数据,而不是引用回区域设置数据。

您可以使用
订阅
(请参阅)来了解
区域设置的值何时发生更改。看见每次更改
locale
的值时,视图模型中的以下可观察订阅将触发。您可以将自己的自定义逻辑放入函数中

self.locale.subscribe(function(){
   alert('locale changed');
});
这个怎么样


或者,对于rwisch45的fiddle来说,这也很有效

您最好的选择是使用客户端i18n解决方案,例如。允许用户动态更改区域设置的问题在于,这将导致极其复杂的UI。否则将成为样板文件的文本(例如,字段标签、选项卡等)需要是可观察的,以便响应您的区域设置中可观察到的更改(最有可能在配置模块中)。这种可配置的可观察性必须被注入到每个模块中,以便驱动区域设置中的可观察变化

我们尝试了你正在采取的方法,发现它给我们带来了沉重的负担。我们选择了一些不引人注目的东西,一些不需要到处可见的东西,只是为了传达语言的变化


@rwisch45建议订阅,这对于一个小的解决方案来说是可行的,而且效果很好。但是订阅不会很好地扩展。

在考虑了这里的答案后,特别是Chuck的答案,这是我能想到的最好的答案:

添加重新填充选项卡数组的订阅,使用键查找更改的区域设置字符串:

self.locale.subscribe(function (data) {
    var newTabs = [];
    ko.utils.arrayForEach(self.tabs(), function(tab) {
        tab.title = data.tabs[tab.key];
        newTabs.push(tab);
    });
    self.tabs(null);
    self.tabs(newTabs);
});

不太好,我意识到我可能没有以正确的方式思考这个问题。幸运的是,大多数本地化都是在html视图中完成的,这很好。

这是我需要帮助的自定义逻辑,而不是subscribe.tabs,这是一个比我在示例中指出的复杂得多的对象。它包含多个属性,其中一个是本地化标题。我的错。我不认为我可以从头开始重写它。尽管我会研究调用一个帮助函数来返回一个新的tabs对象,并根据您的第二个小提琴图使用新的本地化值。请使用敲除法查看此小提琴图中的翻译:。也许这会给你更多的想法。:-)我怀疑你的例子只是简化了你的问题:-)谢谢你的想法。locale实际上是i18next返回的一个可观察值。如图所示,它可以很好地处理数据绑定属性,但不能直接在另一个observableArray中使用。我现在也发现开销越来越大。我可以即时翻译标签和任何可观察的数组,但我还必须从服务器刷新数据,并设置和刷新任何其他组件的区域设置,例如momentjs、kendo。大多数用户实际上只会用一种语言登录,因此开销是不可接受的。@SpaceMonkey很高兴我能提供帮助。有时候你只需要沿着一条路走下去,看看它会走到哪里:)。
<ul data-bind="with: locale">
     <li data-bind="text: tabs.one"></li>
    <li data-bind="text: tabs.two"></li>
</ul>
self.locale.subscribe(function (data) {
    var newTabs = [];
    ko.utils.arrayForEach(self.tabs(), function(tab) {
        tab.title = data.tabs[tab.key];
        newTabs.push(tab);
    });
    self.tabs(null);
    self.tabs(newTabs);
});