AngularJS 作为一款经典的前端 JavaScript 框架,以其数据双向绑定、依赖注入和模块化设计等特点,在构建单页应用(SPA)方面具有独特优势,本文将以一个简单的“猜大小”游戏为例,详细阐述如何使用 AngularJS 实现一个功能完整、交互友好的 Web 应用,涵盖项目结构、核心功能实现、数据绑定逻辑及用户体验优化等关键环节。

项目初始化与基础架构搭建
在开始开发“猜大小”游戏前,首先需要搭建基础的 AngularJS 项目环境,我们可以通过引入 AngularJS 的核心库文件,并结合 HTML、CSS 和 JavaScript 构建一个简洁的前端项目结构。
文件结构设计
一个典型的 AngularJS 小型项目可包含以下文件:
index.html:主页面,包含游戏的 UI 模板。css/style.css:样式文件,用于美化游戏界面。js/app.js:AngularJS 应用主模块定义。js/controller.js:游戏控制器,包含核心业务逻辑。js/diceService.js:自定义服务,处理骰子相关的数据操作。
引入 AngularJS 库
在 index.html 中,通过 <script> 标签引入 AngularJS 的核心库(可通过 CDN 下载):
<script src="https://cdn.jsdelivr.net/npm/angular@1.8.2/angular.min.js"></script>
核心功能模块解析
“猜大小”游戏的核心规则是:玩家猜测两个骰子点数之和的大小(大:7-12,小:2-6),若猜对则获胜,否则失败,以下是各模块的具体实现方法。
应用模块与路由配置(app.js)
AngularJS 应用以模块为基本单位,通过 angular.module() 方法创建和配置模块,对于单页面应用,可结合 ngRoute 模块实现视图路由:
var app = angular.module('guessDiceGame', ['ngRoute']);
app.config(function($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'views/game.html',
controller: 'GameController'
})
.otherwise({
redirectTo: '/'
});
});
这里定义了一个默认路由,指向游戏主页面 game.html,并绑定 GameController 控制器。
游戏控制器逻辑(controller.js)
控制器是连接模型(数据)和视图(模板)的桥梁,负责处理用户交互和业务逻辑,以下是 GameController 的核心代码:

app.controller('GameController', function($scope, DiceService) {
// 初始化游戏数据
$scope.playerGuess = null; // 玩家猜测('big' 或 'small')
$scope.dice1 = 1; // 骰子1点数
$scope.dice2 = 1; // 骰子2点数
$scope.result = ''; // 游戏结果
$scope.isRolling = false; // 骰子是否正在滚动
// 掷骰子方法
$scope.rollDice = function() {
if (!$scope.playerGuess) {
$scope.result = '请先选择大小!';
return;
}
$scope.isRolling = true;
$scope.result = '';
// 模拟骰子滚动动画
var rollInterval = setInterval(function() {
$scope.dice1 = Math.floor(Math.random() * 6) + 1;
$scope.dice2 = Math.floor(Math.random() * 6) + 1;
$scope.$apply(); // 手动触发数据更新
}, 100);
// 1秒后停止滚动,计算结果
setTimeout(function() {
clearInterval(rollInterval);
$scope.isRolling = false;
var sum = $scope.dice1 + $scope.dice2;
var isBig = sum >= 7;
if (($scope.playerGuess === 'big' && isBig) ||
($scope.playerGuess === 'small' && !isBig)) {
$scope.result = '恭喜你,猜对了!点数和为:' + sum;
} else {
$scope.result = '很遗憾,猜错了!点数和为:' + sum;
}
$scope.$apply();
}, 1000);
};
// 重置游戏
$scope.resetGame = function() {
$scope.playerGuess = null;
$scope.dice1 = 1;
$scope.dice2 = 1;
$scope.result = '';
};
});
关键逻辑说明:
- 数据绑定:通过
$scope将数据与模板关联,实现视图与模型的自动同步(如$scope.dice1变化时,模板中对应的骰子点数实时更新)。 - 用户交互:
rollDice()方法处理玩家点击“掷骰子”按钮的逻辑,包括验证玩家是否已选择大小、模拟骰子滚动动画、计算最终结果等。 - 异步操作:使用
setInterval和setTimeout实现骰子滚动动画,并通过$scope.$apply()确保异步操作后数据变化能反映到视图。
自定义服务封装(diceService.js)
为了提高代码复用性和可维护性,可将骰子相关的数据操作封装为服务。
app.service('DiceService', function() {
// 生成随机骰子点数
this.rollDice = function() {
return {
dice1: Math.floor(Math.random() * 6) + 1,
dice2: Math.floor(Math.random() * 6) + 1
};
};
});
服务通过依赖注入(DI)机制被控制器调用,实现业务逻辑与数据操作的分离。
视图模板设计(views/game.html)
视图模板使用 AngularJS 的指令(如 ng-model、ng-click、ng-show)绑定控制器中的数据和事件:
<div ng-controller="GameController">
<h1>猜大小游戏</h1>
<!-- 玩家选择 -->
<div class="selection">
<label>请选择:</label>
<input type="radio" name="guess" value="big" ng-model="playerGuess"> 大(7-12)</input>
<input type="radio" name="guess" value="small" ng-model="playerGuess"> 小(2-6)</input>
</div>
<!-- 骰子显示区域 -->
<div class="dice-container">
<div class="dice" ng-class="{ 'rolling': isRolling }">
{{ dice1 }}
</div>
<div class="dice" ng-class="{ 'rolling': isRolling }">
{{ dice2 }}
</div>
</div>
<!-- 操作按钮 -->
<div class="actions">
<button ng-click="rollDice()" ng-disabled="isRolling || !playerGuess">掷骰子</button>
<button ng-click="resetGame()">重置</button>
</div>
<!-- 结果显示 -->
<div class="result" ng-bind="result"></div>
</div>
核心指令解析:
ng-model:将单选按钮的值绑定到$scope.playerGuess,实现双向数据绑定。ng-click:绑定按钮点击事件,触发控制器中的方法。ng-disabled:根据条件禁用按钮(如骰子滚动时禁用“掷骰子”按钮)。ng-class:动态添加 CSS 类(如骰子滚动时添加rolling类,实现动画效果)。ng-bind:安全地显示数据结果,避免 XSS 攻击。
样式美化(css/style.css)
通过 CSS 为游戏界面添加样式,提升用户体验:
.dice-container {
display: flex;
justify-content: center;
margin: 20px 0;
}
.dice {
width: 60px;
height: 60px;
border: 2px solid #333;
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
font-size: 24px;
font-weight: bold;
background-color: #fff;
margin: 0 10px;
}
.rolling {
animation: roll 0.1s infinite;
}
@keyframes roll {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.actions button {
padding: 10px 20px;
margin: 0 5px;
font-size: 16px;
cursor: pointer;
}
.result {
margin-top: 20px;
font-size: 18px;
color: #d9534f;
}
数据绑定与交互优化
AngularJS 的核心优势在于数据双向绑定,它能够自动同步模型和视图的变化,减少手动 DOM 操作,在“猜大小”游戏中,数据绑定体现在以下几个方面:

- 玩家选择与视图同步:当玩家点击“大”或“小”单选按钮时,
ng-model指令将值自动更新到$scope.playerGuess,无需手动获取 DOM 元素值。 - 骰子点数实时显示:控制器中
$scope.dice1和$scope.dice2的变化会通过 插值表达式实时反映到视图,骰子滚动动画期间点数不断更新,增强视觉体验。 - 按钮状态控制:通过
ng-disabled指令,根据$scope.isRolling和$scope.playerGuess的状态动态禁用或启用按钮,避免玩家在骰子滚动时重复点击或未选择大小就掷骰子。
功能扩展与用户体验提升
在基础功能实现后,可通过以下方式扩展游戏功能,提升用户体验:
添加游戏统计功能
在控制器中增加统计变量,记录玩家的胜负次数:
$scope.wins = 0;
$scope.losses = 0;
// 在 rollDice 方法中更新统计
if (/* 猜对 */) {
$scope.wins++;
} else {
$scope.losses++;
}
在模板中添加统计信息显示:
<div class="stats">
<p>胜利:{{ wins }} 次,失败:{{ losses }} 次</p>
</div>
实现骰子点数动画
使用 CSS3 动画或第三方库(如 animate.css)为骰子添加更丰富的滚动效果,
.dice.rolling {
animation: roll 0.1s infinite, bounce 0.5s ease-in-out infinite alternate;
}
@keyframes bounce {
0% { transform: translateY(0); }
100% { transform: translateY(-10px); }
}
本地存储游戏记录
利用浏览器的 localStorage 保存玩家的胜负统计,刷新页面后数据不丢失:
// 初始化时读取本地存储
$scope.wins = parseInt(localStorage.getItem('wins')) || 0;
$scope.losses = parseInt(localStorage.getItem('losses')) || 0;
// 更新统计时保存到本地存储
$scope.$watchCollection(['wins', 'losses'], function(newValues) {
localStorage.setItem('wins', newValues[0]);
localStorage.setItem('losses', newValues[1]);
});
通过 AngularJS 实现“猜大小”游戏,我们充分体验了框架的核心特性:模块化设计、数据双向绑定、依赖注入等,从项目结构搭建到功能模块实现,再到交互优化和功能扩展,AngularJS 提供了一套完整的开发范式,使代码结构清晰、易于维护,尽管现代前端框架(如 Angular、React、Vue)在性能和生态上已有所超越,但 AngularJS 作为前端框架的先驱,其设计思想和实现原理仍对理解前端开发具有重要的学习价值,通过这样的实践项目,开发者能够更好地掌握 AngularJS 的核心概念,并将其应用到更复杂的应用开发中。