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 问题,并且您的视图模型没有按应有的方式构建。
我要创建的是一个使用 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 问题,并且您的视图模型没有按应有的方式构建。