Knockout.js: вызывать функцию на прототипе, но оставаться в контексте foreach
Я пытаюсь создать простую игру в крестики-нолики с использованием knockout.js. Я также использую Jade в качестве препроцессора; дайте мне знать, если вас это смущает, но это должно быть довольно просто.
Поэтому мне нужно использовать функцию для моих объектов в моей привязке данных foreach в моем HTML, но мне также нужно иметь доступ к другим объектам в viewModel. Я не совсем уверен, как это сделать. Я могу получить доступ к функции, если я помещу ее в объекты в foreach, но тогда я не могу получить доступ к объектам вне этого объекта.
Итак, мой вопрос: как мне вызвать функцию из контекста foreach, который имеет доступ ко всему на viewModel?
Вот мой код:
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())
1 ответ
Привыкайте помещать всю логику в модель представления / javascript, а не в представление. Кроме того, прочитайте click
Обязательная документация обработчика, на самом деле она отвечает на большинство ваших вопросов и является лишь кратким чтением.
В основном это:
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
}
Если вам нужно получить доступ к элементам между "потомком" и "корнем" (то есть там лежит $parent
между) вы должны либо:
- Переместить
changeSymbol
функция к$parent
и убедитесь, что модель родительского представления имеет ссылку на своего родителя, если вам нужно использовать это внутри функции; или же - Поместите свойство для родителя в дочерний vm, чтобы функция могла вызывать
childVm.parent
чтобы добраться до этой модели представления.
Как примечание ноги, если вам абсолютно необходимо, вы можете сделать это:
td(data-bind="text:symbol, click: function() { $root.changeSymbol($root, $parent, $data); }")
Но это, вероятно, означает, что у вас есть проблема XY, и ваши модели представлений не структурированы так, как они должны быть.