【问题标题】:pass the value from one viewmodel to another viewmodel in knockoutjs在 knockoutjs 中将值从一个视图模型传递到另一个视图模型
【发布时间】:2014-04-03 18:29:36
【问题描述】:

当我搜索时,我发现,如何将值从 viewmodel 绑定到 view 而不是 viewmodel 到 viewmodel 我需要将一个属性值从一个视图模型传递到另一个视图模型,因为我需要在第一个视图模型中更新初始属性,然后我想在另一个视图模型中使用它。因为它在测试时很有帮助。

假设下面的视图模型是第一个视图模型,

var xx = xx || {};
    xx.yyy = xx.yyy || {};
    xx.yyy.zzz = function(object ) {
    var model = {};
    model.isTested= ko.observable(false);

   //below is the anonymous call to get the value(true/false):
    datasource.someFeatureEnable.isTested().done(function (featureToggle) {
    model.isTested(featureToggle.enabled);                
    });
}

我想在另一个视图模型中传递 isTested(true/false) 属性值,因为要正确运行我的应用程序并让我的测试通过

【问题讨论】:

    标签: knockout.js


    【解决方案1】:

    这取决于两个视图模型是否在内存中并同时可用。如果是这样,那么striceman 使用淘汰邮箱的建议是一个很好的建议。或者,您可以使用客户端消息总线,例如 postal.js(这是我使用的)。

    如果视图模型不在内存中并且同时可用,则需要引入第三个静态对象(我们将其称为“Z”)来处理类似于事件聚合器模式。本质上,viewmodel-1 将直接引用 Z 以将 isTested 值存储在那里。当 viewmodel-2 实例化时,它会检查 Z 以获得 isTested 值。这种方法并不是真正的事件聚合,因为您没有在通道上发布消息(尽管,如果您采用将带有有效负载的消息发送到 Z 的方法,那么它会比它需要的复杂得多在这种情况下)。

    如果您使用的是 AMD(比如说,require),您只需在每个视图模型中(或者实际上,在依赖于 Z 的每个视图模型中)都需要 Z。您可以在 http://www.requirejs.org 阅读有关 require 的信息。

    裸露的骨头,我们会:

    viewmodel-1

    this.isTested = ko.observable(false);
    var Z = require("Z");
    Z.isTested(this.isTested());
    

    viewmodel-2

    this.isTested = false;  //Making the assumption that isTested doesn't have to be observable here--but it could be
    
    var Z = require("Z");
    this.isTested = Z.isTested();
    

    当然,您会对此进行详细说明,以便 Z 可以处理视图模型数组,也许使用可以查找相关视图模型的字典对象。

    不过,我会告诫不要吓人的方法,即让视图模型相互依赖。如果您有许多具有isTested 关系的视图模型,则依赖关系图可能会变得非常复杂。我会将isTested 和其他属性集中在一个第三方模块中:Z。

    我要重申 Z 应该是静态的。这意味着它应该返回一个对象字面量,而不是构造函数。

    作为最后一点,顺便说一下,我建议使用中介者模式。我并不是建议 Z 应该存储对 viewmodel-1 和 viewmodel-2 的引用。

    【讨论】:

      【解决方案2】:

      您可以让您的第二个视图模型依赖于您的第一个视图模型。

      //this is the definition of your first view model.
      function MainViewModel(dataSource) {
        var self = this;
        this.DataSource = dataSource;
        this.isTested = ko.observable(false);
      
        //a callable function that will run isTested check on someFeatureEnable
        this.TestSomeFeature = function() {
            self.DataSource.someFeatureEnable.isTested().done(function (featureToggle) {
                self.isTested(featureToggle.enabled);                
            });
        };
        return this;
      }
      //this is the definition of your second viewmodel
      function SubViewModel(mainViewModel) {
        var self = this;
        self._mainViewModel = mainViewModel;
        //for read only access
        self.MainIsTested = function() { return self._mainViewModel.isTested(); }
        //for read/write
        self.MainIsTestedReference = self._mainViewModel.isTested
        return self;
      }
      
      
      
      //this is the code that initializes the whole page.
      var main = new MainViewModel();
      var sub = new SubViewModel(main);
      //now run the check
      main.TestSomeFeature();
      
      //these are examples, showing how to get at the isTested property in your various viewmodels. The comments are what the code should return
      sub.MainIsTested(); //false
      main.isTested(); //false
      //set isTested to true from the sub
      sub.MainIsTestedReference(true);
      //now main isTested returns true, because the sub viewmodel and the main viewmodel have references to the same object.
      main.isTested(); // true
      

      如果您想要更高级并使用基于事件的方法,我建议您查看 ko.postbox,查看这些参考资料。

      http://www.knockmeout.net/2012/05/using-ko-native-pubsub.html

      https://github.com/rniemeyer/knockout-postbox

      【讨论】:

      • 嗨,吓人 :)...感谢您的快速响应。我对上面的代码并不完全清楚。请提及哪些代码行将成为第一个视图模型的一部分,哪些代码行将是第二视图模型的一部分?
      • 我添加了一些cmets,希望代码对你来说更清楚。从您的 StackOverflow 分数来看,您似乎在 javascript 和淘汰赛方面相对缺乏经验。我建议您浏览learn.knockoutjs.com 上的教程,然后,如果您想了解更多关于 javascript 的信息,或了解淘汰教程中代码背后的原因,请查看addyosmani.com/resources/essentialjsdesignpatterns/book。它冗长而密集,但非常好。请务必查看第一部分的阅读清单。
      【解决方案3】:

      我会使用事件聚合器模式,这是一种解耦且功能强大的方式,任何侦听器都可以在不耦合到发布者的情况下侦听任何事件。

      您可以查看我是如何为这个库(SignalR 库)做到这一点的

      https://github.com/AndersMalmgren/SignalR.EventAggregatorProxy/

      为了您的方便,我只提取了客户端代码

      http://jsfiddle.net/ezkGt/

      基本上你对 pub/sub 所做的是

      signalR.eventAggregator.subscribe(Event, listener.onEvent, listener);
      
      setInterval(function() {
          signalR.eventAggregator.publish(new Event(new Date()));
      }, 500);
      
      setTimeout(function() {
          signalR.eventAggregator.unsubscribe(listener);
      }, 5000);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-01-18
        • 1970-01-01
        • 2014-10-08
        • 2013-03-02
        • 1970-01-01
        • 2018-10-29
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多