Knockout.js:在原型上调用函数但留在 foreach 的上下文中

Knockout.js: call function on the prototype but stay in the context of the foreach

我要创建的是一个使用 knockout.js 的基本井字游戏。我也在使用 jade 作为预处理器;如果您对此感到困惑,请告诉我,但它应该非常简单明了。

所以我需要在 HTML 的 foreach 数据绑定中对我的对象使用一个函数,但我还需要访问 viewModel 中的其他对象。我不太清楚该怎么做。如果我将它放在 foreach 中的对象上,我可以访问该函数,但是我无法访问该对象之外的对象。

所以我的问题是:如何从可以访问 viewModel 上所有内容的 foreach 上下文调用函数?

这是我的代码:

HTML

table.bg-success(style="table-layout:fixed;")
  tr#row1(data-bind="foreach:topRow")

    td(data-bind="text:symbol,click:function(){$parent.PlayerTurn.bind($root)();$root.changeSymbol()}")

  tr#row2(data-bind="foreach:middleRow")
    td(data-bind="text:symbol,click:function(){$parent.PlayerTurn.bind($root)();$root.changeSymbol()}") 

  tr#row3(data-bind="foreach:bottomRow")
    td(data-bind="text:symbol,click:function(){$parent.PlayerTurn.bind($root)();$root.changeSymbol()}")

JAVASCRIPT

var aBox = (function(position){
  function ABox(){
    this.symbol = ko.observable("");
    this.position = position
    this.count = 0;

  }

  return ABox;
})()

var viewModel = (function(){
  function ViewModel(){
    this.theMessage = new message();
    this.thePlayers = new players();
    this.topRow = ko.observableArray([
      new aBox("r1c1"),
      new aBox("r1c2"),
      new aBox("r1c3"),     
    ]);
    this.middleRow = ko.observableArray([
      new aBox("r2c1"),
      new aBox("r2c2"),
      new aBox("r2c3"),
    ]);
    this.bottomRow = ko.observableArray([
      new aBox("r3c1"),
      new aBox("r3c2"),
      new aBox("r3c3"),
    ]);     
  }

    ViewModel.prototype.changeSymbol = function(){
      this.count+=1;
      if(this.count%2==0){
      this.symbol("O");
      }else{
        this.symbol("X")
      }
    }    

  return ViewModel;
})()

ko.applyBindings(new viewModel())

养成将所有 逻辑放在视图模型/javascript 中的习惯,而不是在视图中。另外,通读 the click binding handler documentation 它实际上回答了你的大部分问题,而且只是简短的阅读。

基本上,这个:

td(data-bind="text:symbol, click: $root.changeSymbol") 

那么你可以在$root上使用这个功能:

var self = this;
self.changeSymbol = function(childVm) {
  console.log(self); // is the $root
  console.log(childVm); // the item from the foreach
}

如果您需要访问在"child"和"root"之间的元素(即中间有一个$parent),您应该:

  • changeSymbol 函数移动到 $parent 并确保父视图模型具有对 its 父视图的引用功能;或
  • 在子 vm 上为父级放置一个 属性,以便该函数可以调用 childVm.parent 来访问该视图模型。

作为脚注,如果您绝对必须,您可以这样做:

td(data-bind="text:symbol, click: function() { $root.changeSymbol($root, $parent, $data); }") 

但这可能意味着您遇到了 XY 问题,并且您的视图模型没有按应有的方式构建。