我相信您过于依赖 jQuery 来实现您的游戏。您只使用 Angular 将 jQuery 事件绑定到 DOM 元素。
你的游戏是 Angular 新手的一个很好的例子,所以我编写了我自己的版本。
看看这个jsfiddle。
JS代码:
angular.module('CardFlipperApp', [])
/* Card model */
.factory('Card', function() {
function Card (number) {
this.visible = false;
this.cleared = false;
this.number = number;
};
Card.prototype.show = function() {
this.visible = true;
};
Card.prototype.hide = function() {
this.visible = false;
};
Card.prototype.clear = function() {
this.cleared = true;
};
return Card;
})
/* Deck model */
.factory('Deck', function(Card) {
function shuffle(array) {
var counter = array.length, temp, index;
while (counter--) {
index = (Math.random() * counter) | 0;
temp = array[counter];
array[counter] = array[index];
array[index] = temp;
}
return array;
}
function Deck (numberOfCards) {
var array = [];
for (var i = 1; i <= numberOfCards; i++) {
array.push(new Card(i));
array.push(new Card(i));
}
this.cards = shuffle(array);
};
Deck.prototype.hideAllBut = function(card) {
for (var i = 0; i < this.cards.length; i++) {
if (this.cards[i] !== card) {
this.cards[i].hide();
}
}
};
Deck.prototype.allCleared = function() {
for (var i = 0; i < this.cards.length; i++) {
if (!this.cards[i].cleared) {
return false;
}
}
return true;
};
return Deck;
})
.controller('CardFlipperCtrl', function($scope, $timeout, Deck) {
var timeoutHandle = null;
function nextTick(){
$scope.timer++;
timeoutHandle = $timeout(nextTick,1000);
}
function startTimer() {
timeoutHandle = $timeout(nextTick, 1000);
}
function stopTimer() {
if (timeoutHandle) {
$timeout.cancel(timeoutHandle);
timeoutHandle = null;
}
}
$scope.init = function() {
$scope.deck = new Deck(9);
stopTimer();
$scope.moves = 0
$scope.timer = 0;
$scope.done = false;
};
$scope.toggle = function(card) {
// double click, do nothing
if ($scope.selectedCard === card) { return; }
$scope.moves++;
if ($scope.moves === 1) { // start timer on 1st move
startTimer();
}
if ($scope.selectedCard) {
if ($scope.selectedCard.number === card.number) {
$scope.selectedCard.clear();
card.clear();
if ($scope.deck.allCleared()) {
$scope.done = true;
stopTimer();
}
} else {
card.show();
}
$scope.selectedCard = null;
} else {
card.show();
$scope.deck.hideAllBut(card);
$scope.selectedCard = card;
}
};
$scope.init(); // initial deck creation
});
模板:
<div ng-app="CardFlipperApp">
<div ng-controller="CardFlipperCtrl">
<button ng-click="init()">Reset</button>
Moves: {{moves}} - Time: {{timer}}
<div ng-if="!done" ng-repeat="card in deck.cards">
<div class="card" ng-class="{visible: card.visible, cleared: card.cleared, changeLine: ($index % 6 == 0)}" ng-click="toggle(card)">
<span ng-if="card.visible">{{card.number}}</span>
</div>
</div>
<div ng-if="done" class="done">Done!</div>
</div>
</div>
注意像 Card and Deck 这样的“模型”的使用。模型不是 Angular 特有的东西(jQuery 应用程序可以抽象这些实体),但在 Angular 中,模型可以在 IOC 内注册为服务并利用 DI(Deck 依赖于 Card,控制器依赖于 Deck)。
我发现这样做的最佳方式是在服务中定义一个普通的 JS“类”(属性、方法、“静态”函数等)并返回要在 Angular 中注册的构造函数。另一个依赖它的组件,只需调用 new ModelClass()。
您的应用程序的大量功能可以驻留在“模型”(与 Angular 无关的代码)中。这样,您的应用程序就更易于阅读、理解和测试。