1 引言:什么是AngularJS?
AngularJS是由Misko Hevery和Adam Abrons于2009年创建的一个开源前端JavaScript框架,后来被Google收购并维护。它旨在克服HTML在构建动态Web应用方面的不足,通过扩展HTML的语法和能力,使开发单页面应用程序(SPA)变得更加高效和结构化。
AngularJS的核心定位是提供一个完整的客户端解决方案,而不仅仅是应用中的一小部分。它采用了声明式编程范式,与传统的命令式编程形成对比,使开发者能够更专注于业务逻辑而非DOM操作。
尽管现在有更现代的替代品(如Angular、React和Vue),但理解AngularJS的架构和设计理念对于学习前端开发演变历程以及维护遗留系统仍然具有重要意义。截至2023年,AngularJS仍被许多企业和项目使用,尤其是那些早期构建的大型企业应用。
2 AngularJS的技术特点
2.1 双向数据绑定
AngularJS最引人注目的特性是其双向数据绑定机制。传统Web开发中,需要手动将数据模型的变化同步到视图,以及将视图中的用户输入同步回数据模型,这个过程既繁琐又容易出错。
AngularJS通过脏检查机制自动完成这一过程:当数据模型发生变化时,视图会自动更新;当用户与视图交互时,数据模型也会自动更新。这大大减少了开发者需要编写的样板代码。
// HTML视图
<div ng-app="myApp" ng-controller="myCtrl">
<input type="text" ng-model="name">
<p>Hello, {{name}}!</p>
</div>
// JavaScript代码
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.name = "AngularJS User";
});
在这个经典示例中,输入框中的内容变化会自动更新到$scope.name,而$scope.name的变化也会自动反映在段落显示中,无需任何手动DOM操作。
2.2 模块化设计与依赖注入
AngularJS采用模块化开发理念,允许开发者将应用拆分为多个模块,每个模块负责不同的功能。这种模块化设计提高了代码的可维护性和可测试性。
与模块化紧密相关的是依赖注入(Dependency Injection)系统。组件不必手动创建它所依赖的其他组件,而是由AngularJS的注入器自动提供:
// 定义一个模块
var app = angular.module('myApp', []);
// 定义服务
app.service('hexafy', function() {
this.func = function(num) {
return num.toString(16);
}
});
// 控制器中注入服务
app.controller('myCtrl', function($scope, hexafy) {
$scope.hexValue = hexafy.func(255); // 使用服务
});
这种依赖注入机制降低了组件之间的耦合度,使代码更加模块化和可测试。
2.3 MVC/MVVM架构模式
AngularJS实现了MVC(Model-View-Controller)或MVVM(Model-View-ViewModel)架构模式,将应用的不同关注点分离:
-
Model(模型):代表应用程序的数据和业务逻辑
-
View(视图):用户看到的界面,负责数据展示
-
Controller(控制器):连接视图和模型,处理用户输入和业务逻辑
在AngularJS中,视图是HTML模板,控制器是JavaScript类,模型则是作用域(Scope)上的数据。
2.4 指令系统与扩展的HTML
AngularJS通过指令扩展了HTML的功能,允许开发者创建自定义的HTML标签和属性。指令是AngularJS中最强大的特性之一,它可以用于操作DOM、添加事件监听器等。
内置指令如ng-app、ng-model、ng-bind等提供了基本功能,而开发者也可以创建自定义指令来封装复杂的UI组件和行为。
3 AngularJS的架构体系
3.1 模块(Modules)
在AngularJS中,模块是组织的核心单元。每个AngularJS应用至少有一个模块(根模块),复杂应用则通常由多个模块组成:
// 创建模块
var app = angular.module('myApp', []);
// 配置模块
app.controller('MyController', function($scope) {
// 控制器逻辑
});
app.service('MyService', function() {
// 服务逻辑
});
模块提供了一种将相关组件(控制器、服务、指令等)组织在一起的方式,并管理它们之间的依赖关系。
3.2 作用域(Scope)与数据绑定
作用域是AngularJS中一个关键概念,它是连接控制器和视图的桥梁。作用域是一个JavaScript对象,拥有属性和方法,这些属性和方法可在视图和控制器中使用。
AngularJS作用域具有层级结构,形成了一个作用域树,与DOM结构相对应。根级作用域为$rootScope,其他作用域均为其子作用域:
app.controller('ParentController', function($scope, $rootScope) {
$scope.parentVar = "父作用域变量"; // 仅在当前控制器可用
$rootScope.globalVar = "全局变量"; // 在整个应用中都可用
});
app.controller('ChildController', function($scope) {
// 可以访问父作用域和$rootScope中的变量
console.log($scope.parentVar);
console.log($scope.$parent.parentVar); // 访问父作用域
});
作用域的层级结构使得数据共享和隔离变得灵活而强大。
3.3 控制器(Controllers)
控制器负责管理视图关联的业务逻辑。它们是常规的JavaScript构造函数,通过$scope对象与视图进行数据交互:
app.controller('MyController', function($scope) {
// 初始化模型数据
$scope.users = [
{name: '张三', age: 12, score: 78},
{name: '李四', age: 12, score: 66}
];
// 定义方法处理用户交互
$scope.addUser = function() {
$scope.users.push({name: $scope.newName, age: 12, score: 0});
};
});
控制器的设计遵循单一职责原则,每个视图通常有对应的控制器。
3.4 服务(Services)
AngularJS中的服务是单例对象,用于封装可重用的业务逻辑。AngularJS提供了多种创建服务的方式:
-
Service:使用构造函数模式,通过
new关键字实例化 -
Factory:返回对象字面量的工厂函数
-
Provider:可在配置阶段使用的更复杂的服务创建方式
// Service示例
app.service('hexafy', function() {
this.gongneng = "将十进制数转化为16进制";
this.func = function(num) {
return num.toString(16);
}
});
// 在控制器中使用服务
app.controller('myCtrl', function($scope, hexafy) {
$scope.hexValue = hexafy.func(255);
});
AngularJS还提供了许多内置服务,如$http用于HTTP请求、$timeout用于延迟执行、$interval用于定期执行等。
4 常用组件与指令
4.1 核心指令
AngularJS提供了丰富的指令来扩展HTML的功能:
-
ng-app:定义AngularJS应用的根元素,自动初始化应用
-
ng-model:实现表单元素与模型数据的双向绑定
-
ng-bind:将模型数据绑定到HTML元素的文本内容
-
ng-controller:为HTML元素指定控制器
-
ng-repeat:循环遍历数组或对象,为每个项生成HTML
-
ng-if/ng-show/ng-hide:条件性地显示或隐藏元素
-
ng-click:处理元素的点击事件
4.2 过滤器
过滤器用于格式化显示给用户的数据,可以在模板、控制器或服务中使用。AngularJS提供了多种内置过滤器:
<!-- 在模板中使用过滤器 -->
<p>{{123.456 | currency}}</p> <!-- 格式化为货币:$123.46 -->
<p>{{'HELLO' | lowercase}}</p> <!-- 转换为小写:hello -->
<p>{{123.45678 | number:2}}</p> <!-- 保留两位小数:123.46 -->
<p>{{today | date:'yyyy-MM-dd'}}</p> <!-- 格式化日期 -->
开发者也可以创建自定义过滤器:
app.filter('reverse', function() {
return function(text) {
return text.split("").reverse().join("");
}
});
4.3 路由与深度链接
AngularJS通过$routeProvider提供路由功能,使构建单页面应用(SPA)成为可能。路由允许定义不同的URL对应不同的视图和控制器:
app.config(['$routeProvider', function($routeProvider) {
$routeProvider
.when('/home', {
templateUrl: 'views/home.html',
controller: 'HomeController'
})
.when('/about', {
templateUrl: 'views/about.html',
controller: 'AboutController'
})
.otherwise({
redirectTo: '/home'
});
}]);
这种机制使得应用能够实现深度链接,即每个"页面"都有唯一的URL,用户可以 bookmark 或分享链接。
5 相似框架对比
5.1 与Angular(2+)的区别
虽然名称相似,但AngularJS(1.x)与Angular(2+)是本质上不同的框架:
| 特性 | AngularJS | Angular |
|---|---|---|
| 架构 | MVC/MVVM | 组件化 |
| 语言 | JavaScript | TypeScript |
| 移动支持 | 有限 | 良好(Ionic等) |
| 性能 | 依赖脏检查,性能较低 | 使用变更检测,性能更高 |
| 学习曲线 | 相对平缓 | 较陡峭 |
Angular放弃了AngularJS的许多概念(如作用域、控制器),转而采用基于组件的架构,这使其更适合构建复杂的大型应用。
5.2 与React、Vue的比较
| 特性 | AngularJS | React | Vue |
|---|---|---|---|
| 架构模式 | MVC/MVVM | 虚拟DOM | 组件化 |
| 数据流 | 双向绑定 | 单向数据流 | 双向绑定/单向数据流 |
| 学习曲线 | 中等 | 中等(需学习JSX) | 平缓 |
| 模板语法 | HTML扩展 | JSX | HTML扩展 |
| 状态管理 | 内置(Scope) | 需要Redux/MobX | 需要Vuex/Pinia |
React和Vue都采用了更现代的组件化架构,避免了AngularJS中一些固有的性能问题(如脏检查循环)。
6 市场应用与使用公司
尽管AngularJS是一个相对较老的框架,但它仍然在许多企业和项目中使用。Google在多项产品中使用了AngularJS。其他使用AngularJS的知名公司包括:
-
Google:多项产品中使用AngularJS
-
IBM:部分企业级应用
-
微软:部分内部工具和产品
-
亚马逊:某些管理界面
-
网飞(Netflix):部分客户端界面
-
UPS:物流跟踪系统
-
PayPal:部分支付界面
需要注意的是,随着现代前端框架的兴起,许多公司已开始将原有的AngularJS应用迁移到Angular、React或Vue等更现代的框架。然而,由于AngularJS应用的庞大和复杂,这一迁移过程可能需要数年时间。
7 总结与展望
AngularJS作为前端开发领域的先驱,引入了许多创新的概念,如双向数据绑定、依赖注入、声明式编程等,这些理念深深影响了后续的前端框架设计。
尽管AngularJS存在一些性能问题和架构上的局限性(如作用域层级复杂时性能下降),但它仍然是一个设计精良的框架,特别适合构建中等复杂度的CRUD应用。AngularJS的丰富特性和强大功能,使其成为现代Web应用开发中的重要框架之一。
对于新项目,通常建议选择更现代的框架(如Angular、React或Vue),但对于需要维护或扩展现有AngularJS应用的情况,深入理解其架构和设计理念仍然至关重要。AngularJS的核心理念——如模块化、可测试性和声明式UI构建——将继续影响前端开发的发展方向。
无论你是需要维护现有AngularJS应用,还是想了解前端框架的演变历史,掌握AngularJS的架构知识都将为你提供宝贵的视角,帮助你更好地理解现代前端开发生态。
116

被折叠的 条评论
为什么被折叠?



