AngularJS
AngularJS 简介
AngularJS诞生于2009年,由Misko Hevery 等人创建,后为Google所收购。是一款优秀的前端JS框架,已经被用于Google的多款产品当中。AngularJS有着诸多特性,最为核心的是:MVVM、模块化、自动化双向数据绑定、语义化标签、依赖注入等等。
AngularJS 基本概念
在创建第一个应用程序之前,你需要理解Angular中的一些概念。 在本章,通过一个简单的例子,你可以快速接触Angular中所有重要的部分。 但是,我不会花时间去解释细节,而是着重于帮助你建立一个全局性的"概观"。
| 概念 | 说明 |
|---|---|
| 模板(Template) | 带有Angular扩展标记的HTML |
| 指令(Directive) | 用于通过自定义属性和元素扩展HTML的行为 |
| 模型(Model) | 用于显示给用户并且与用户互动的数据 |
| 作用域(Scope) | 用来存储模型(Model)的语境(context)。模型放在这个语境中才能被控制器、指令和表达式等访问到 |
| 表达式(Expression) | 模板中可以通过它来访问作用域(Scope)中的变量和函数 |
| 编译器(Compiler) | 用来编译 模板(Template),并且对其中包含的指令(Directive)和表达式(Expression)进行实例化 |
| 过滤器(Filter) | 负责格式化表达式(Expression)的值,以便呈现给用户 |
| 视图(View) | 用户看到的内容(即DOM) |
| 数据绑定(Data Binding) | 自动同步模型(Model)中的数据和视图(View)表现 |
| 控制器(Controller) | 视图(View)背后的业务逻辑 |
| 依赖注入(Dependency Injection) | 负责创建和自动装载对象或函数 |
| 注入器(Injector) | 用来实现依赖注入(Injection)的容器 |
| 模块(Module) | 用来配置注入器 |
| 服务(Service) | 独立于视图(View)的、可复用的业务逻辑 |
AngularJS 数据绑定
在Angular网页应用中,数据绑定是数据模型(model)与视图(view)组件的自动同步。Angular的实现方式允许你把应用中的模型看成单一数据源。而视图始终是数据模型的一种展现形式。当模型改变时,视图就能反映这种改变,反之亦然。
代码示例:
xml
<!doctype html>
<html ng-app="myApp">
<head>
<title>AngularJS 数据绑定</title>
<script src="http://code.angularjs.org/1.2.25/angular.min.js"></script>
</head>
<body>
<div ng-controller="myController">
<!-- 单向数据绑定 -->
<p>单项数据绑定:{{message}}</p>
<!-- 双向数据绑定 -->
<label for="inputText">输入内容:</label>
<input type="text" id="inputText" ng-model="inputValue">
<p>双向数据绑定结果:{{inputValue}}</p>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('myController', function ($scope) {
$scope.message = "单向数据绑定";
$scope.inputValue = '';
});
</script>
</body>
</html>
AngularJS 控制器
在 AngularJS 里,控制器(Controller)是至关重要的组件,它承担着管理应用程序数据与行为的职责。
定义与创建
在 AngularJS 里,控制器其实就是一个 JavaScript 函数,借助$scope对象来对数据和行为进行管理。你可以通过angular.module().controller()方法创建控制器。示例如下:
ini
var app = angular.module('myApp', []);
app.controller('myController', function($scope) {
// 这里可以定义数据和方法
$scope.message = 'Hello, AngularJS!';
$scope.sayHello = function() {
alert($scope.message);
};
});
在上述代码中,myApp是应用模块,myController是控制器名称,$scope作为参数传入控制器函数。
使用方法
定义好控制器后,要使用ng - controller指令把它关联到 HTML 元素上。
xml
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<title>AngularJS Controller Example</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular.min.js"></script>
</head>
<body>
<div ng-controller="myController">
<p>{{message}}</p>
<button ng-click="sayHello()">点击打招呼</button>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('myController', function($scope) {
$scope.message = 'Hello, AngularJS!';
$scope.sayHello = function() {
alert($scope.message);
};
});
</script>
</body>
</html>
在这个例子中,ng - controller="myController"把myController控制器和<div>元素关联起来,这样<div>内的子元素 就能访问$scope里的数据和方法了。
作用
管理数据
控制器能够在$scope对象里定义和管理数据,这些数据可以在 HTML 模板中借助数据绑定来显示。
bash
app.controller('myController', function($scope) {
$scope.person = {
name: 'John',
age: 30
};
});
css
<div ng-controller="myController">
<p>姓名: {{person.name}}</p>
<p>年龄: {{person.age}}</p>
</div>
处理业务逻辑
控制器能够定义方法,用来处理用户的交互和业务逻辑。
bash
app.controller('myController', function($scope) {
$scope.calculateSum = function(a, b) {
return a + b;
};
});
css
<div ng-controller="myController">
<p>两数之和: {{calculateSum(2, 3)}}</p>
</div>
监听事件
控制器可以监听并处理 DOM 事件,像点击、输入等。
javascript
app.controller('myController', function($scope) {
$scope.clickHandler = function() {
alert('按钮被点击了!');
};
});
ini
<div ng-controller="myController">
<button ng-click="clickHandler()">点击我</button>
</div>
注意事项
- 单一职责原则 :控制器应当专注于处理特定的业务逻辑,避免承担过多的职责。如果业务逻辑过于复杂,可考虑将部分功能拆分成服务。
- ** <math xmlns="http://www.w3.org/1998/Math/MathML"> s c o p e 的作用域 ∗ ∗ :每个控制器都有自己的 scope的作用域**:每个控制器都有自己的 </math>scope的作用域∗∗:每个控制器都有自己的scope对象, <math xmlns="http://www.w3.org/1998/Math/MathML"> s c o p e 的作用域是嵌套的,子元素可以访问父元素的 scope的作用域是嵌套的,子元素可以访问父元素的 </math>scope的作用域是嵌套的,子元素可以访问父元素的scope。不过要注意避免$scope的滥用,防止作用域污染。
AngularJS 服务
在 AngularJS 里,服务(service)是一种单例对象,主要用于在不同组件(像控制器、指令等)间共享数据和逻辑。
定义与特性
服务是 AngularJS 应用中的一个可注入对象,在整个应用生命周期里,服务实例只有一个,这就是单例特性。此特性让服务成为在不同组件间共享数据和方法的理想选择。
创建服务
AngularJS 提供了多种创建服务的方式,常见的有以下几种:
(1)service方式
ini
var app = angular.module('myApp', []);
app.service('myService', function() {
this.getData = function() {
return [1, 2, 3];
};
});
在这个例子中,myService就是一个服务,它有一个getData方法,返回一个数组。
(2)factory方式
ini
app.factory('myFactory', function() {
var factory = {};
factory.getData = function() {
return [4, 5, 6];
};
return factory;
});
factory方式返回一个对象,这个对象包含了服务的方法和数据。
(3)provider方式
ini
app.provider('myProvider', function() {
this.$get = function() {
var provider = {};
provider.getData = function() {
return [7, 8, 9];
};
return provider;
};
});
provider方式相对复杂,它可以在配置阶段进行配置,然后在运行时通过$get方法返回服务实例。
常用服务类型
1)内置服务
$http
用于发送 HTTP 请求,和服务器进行数据交互。
lua
app.controller('myController', function($scope, $http) {
$http.get('https://api.example.com/data')
.then(function(response) {
$scope.data = response.data;
}, function(error) {
console.error('请求出错:', error);
});
});
$timeout
类似于 JavaScript 的setTimeout函数,用于延迟执行代码。
php
app.controller('myController', function($scope, $timeout) {
$timeout(function() {
$scope.message = '延迟显示的消息';
}, 2000);
});
$interval
类似于 JavaScript 的setInterval函数,用于定时执行代码。
ini
app.controller('myController', function($scope, $interval) {
var counter = 0;
var interval = $interval(function() {
counter++;
$scope.counterValue = counter;
}, 1000);
// 可以在适当的时候取消定时器
$scope.cancelInterval = function() {
$interval.cancel(interval);
};
});
2)自定义服务
开发者可以根据业务需求创建自定义服务,用于封装特定的业务逻辑。比如,创建一个处理用户认证的服务:
ini
app.service('authService', function() {
this.isAuthenticated = false;
this.login = function(username, password) {
// 模拟登录逻辑
if (username === 'admin' && password === 'password') {
this.isAuthenticated = true;
return true;
}
return false;
};
this.logout = function() {
this.isAuthenticated = false;
};
});
使用场景
- 数据共享:不同的控制器或指令需要访问相同的数据时,可使用服务来共享这些数据。例如,多个页面需要显示用户的登录信息,就可以把用户信息存储在一个服务里。
- 业务逻辑封装:将一些通用的业务逻辑封装在服务中,提高代码的可复用性和可维护性。例如,将数据验证、加密解密等逻辑封装在服务里。
- 与服务器交互 :使用
$http服务或自定义服务来处理与服务器的通信,将数据请求和处理逻辑封装在服务中,让控制器更加简洁。
AngularJS 作用域
在 AngularJS 里,作用域(Scope)是一个核心概念,它充当着数据模型和视图之间的桥梁,负责在两者间进行数据绑定和事件传递。
定义
作用域是一个对象,它包含了应用程序的数据和方法,并且有层级结构。AngularJS 应用中,每个控制器、指令都有与之关联的作用域,作用域提供了一个上下文环境,在这个环境里可以定义和管理数据与行为。
类型
1. 根作用域($rootScope)
- 定义 :
$rootScope是所有作用域的顶级作用域,在整个 AngularJS 应用中只有一个$rootScope实例。当应用启动时,AngularJS 会自动创建$rootScope。 - 作用 :可以在
$rootScope上定义全局的数据和方法,让应用中的所有子作用域都能访问。不过要谨慎使用,因为过多使用全局数据可能导致代码难以维护和调试。
ini
var app = angular.module('myApp', []);
app.run(function($rootScope) {
$rootScope.globalMessage = '这是全局消息';
});
2. 子作用域
- 定义 :每个控制器和指令都会创建自己的子作用域,子作用域继承自其父作用域(通常是
$rootScope或上级控制器的作用域)。 - 作用:用于管理局部的数据和行为。不同的控制器和指令可以有自己独立的子作用域,保证数据和逻辑的隔离。
bash
app.controller('myController', function($scope) {
$scope.localMessage = '这是局部消息';
});
特性
1. 作用域继承
子作用域会继承父作用域的属性和方法。当在子作用域中访问一个属性时,AngularJS 会先在子作用域中查找,如果找不到,会继续在父作用域中查找,以此类推,直到找到该属性或到达$rootScope。
xml
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<title>Scope Inheritance</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular.min.js"></script>
</head>
<body>
<div ng-controller="parentController">
<p>父作用域消息: {{message}}</p>
<div ng-controller="childController">
<p>子作用域访问父作用域消息: {{message}}</p>
</div>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('parentController', function($scope) {
$scope.message = '来自父作用域的消息';
});
app.controller('childController', function($scope) {
// 子作用域可以访问父作用域的 message 属性
});
</script>
</body>
</html>
2. 作用域隔离
某些指令(如自定义指令)可以创建隔离作用域,隔离作用域不继承父作用域的属性和方法,通过特定的绑定策略与父作用域进行数据交互。这样可以避免作用域之间的相互影响,提高指令的复用性。
javascript
app.directive('myDirective', function() {
return {
scope: {
// 创建隔离作用域
data: '=' // 双向数据绑定
},
template: '<p>隔离作用域数据: {{data}}</p>'
};
});
生命周期
1. 创建
当 AngularJS 应用启动时,会创建$rootScope。在创建控制器、指令等组件时,会相应地创建子作用域。
2. 链接
作用域会与对应的 DOM 元素进行链接,建立数据绑定和事件监听。
3. 变更检测
AngularJS 会定期(如用户交互、异步操作完成等)触发变更检测机制,检查作用域中的数据是否发生变化。如果数据发生变化,会更新对应的视图。
4. 销毁
当对应的 DOM 元素被移除或组件被销毁时,作用域也会被销毁,释放内存资源。可以通过$scope.$destroy()方法手动销毁作用域。
注意事项
- 作用域污染 :要避免在
$rootScope上定义过多的全局数据,防止作用域污染,使代码难以维护。 - 作用域链查找:由于作用域链查找机制,过多的嵌套作用域可能会影响性能。在设计应用时,要合理规划作用域的层级结构。
AngularJS 依赖注入
依赖注入(Dependency Injection,简称 DI)是 AngularJS 框架的一个核心特性,它能提升代码的可测试性、可维护性与可扩展性。
定义
依赖注入是一种设计模式,它允许对象在创建时不直接创建或管理其依赖项,而是通过外部传入的方式来获取这些依赖项。在 AngularJS 里,依赖注入用于将服务、值、常量等注入到控制器、指令、过滤器等组件中,使组件间的耦合度降低。
工作原理
AngularJS 的依赖注入系统借助$injector服务来实现。当 AngularJS 应用启动时,会创建一个$injector实例,它负责管理和解析所有的依赖项。在组件(如控制器)定义时,声明所需的依赖项名称,$injector会根据这些名称查找并注入相应的依赖项实例。
注入方式
1. 隐式注入
bash
var app = angular.module('myApp', []);
app.controller('myController', function($scope, $http) {
// 使用 $scope 和 $http 服务
$http.get('https://api.example.com/data')
.then(function(response) {
$scope.data = response.data;
});
});
在这个例子中,AngularJS 根据函数参数名$scope和$http自动注入对应的服务。不过,这种方式在代码经过压缩工具处理后,参数名会被改变,从而导致注入失败。
2. 显式注入
bash
app.controller('myController', ['$scope', '$http', function($scope, $http) {
$http.get('https://api.example.com/data')
.then(function(response) {
$scope.data = response.data;
});
}]);
这种方式通过一个数组来指定依赖项名称,数组的最后一个元素是实际的控制器函数,前面的元素依次是要注入的依赖项名称。这样即使代码被压缩,AngularJS 也能根据数组中的名称正确注入依赖项。
3. $inject属性注入
bash
function MyController($scope, $http) {
$http.get('https://api.example.com/data')
.then(function(response) {
$scope.data = response.data;
});
}
MyController.$inject = ['$scope', '$http'];
app.controller('myController', MyController);
这种方式是将依赖项名称通过$inject属性添加到函数上,同样能避免代码压缩带来的问题。
实际应用场景
1. 服务注入
在控制器、指令等组件中注入服务,以实现数据共享和业务逻辑封装。例如,注入$http服务来与服务器进行数据交互:
javascript
app.service('dataService', function($http) {
this.getData = function() {
return $http.get('https://api.example.com/data');
};
});
app.controller('myController', ['$scope', 'dataService', function($scope, dataService) {
dataService.getData()
.then(function(response) {
$scope.data = response.data;
});
}]);
2. 配置注入
在应用配置阶段注入常量和值,用于配置服务或模块。例如:
javascript
app.constant('API_URL', 'https://api.example.com');
app.service('dataService', ['$http', 'API_URL', function($http, API_URL) {
this.getData = function() {
return $http.get(API_URL + '/data');
};
}]);
优点
- 可测试性:通过依赖注入,能方便地替换依赖项为模拟对象,从而进行单元测试。
- 可维护性:降低组件间的耦合度,使代码更易于理解和修改。
- 可扩展性:可以轻松地添加或替换依赖项,而不影响其他组件。
AngularJS 模板
在 AngularJS 里,模板是用户界面的蓝图,它把静态 HTML 和动态数据及逻辑相结合,最终生成用户看到的页面。
定义
AngularJS 模板本质上是 HTML 文件,不过其中融入了 AngularJS 的特定语法和指令,这些内容能让模板动态地展示数据、处理事件和控制页面结构。
模板语法
在Angular中有以下元素属性可以直接在模板中使用:
- 表达式(Expressions) :用双括号 {{ }} 给元素绑定表达式。
- 指令(Directive) :一个可扩展已有DOM元素或者代表可重复使用的DOM组件,用扩展属性(或者元素)标记。
- 过滤器(Filter) :格式化数据显示在界面上。
- 表单控件(Form Control) :验证用户输入。
1. 插值表达式(双大括号)
插值表达式用双大括号{{ }}表示,用于在 HTML 中显示 AngularJS 作用域(scope)中的数据。示例如下:
xml
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<title>插值表达式示例</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular.min.js"></script>
</head>
<body>
<div ng-controller="myController">
<p>你好,{{name}}!</p>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('myController', function($scope) {
$scope.name = '张三';
});
</script>
</body>
</html>
在这个例子中,{{name}}会被$scope中的name属性值(即 "张三")替代。
2. 指令
指令是 AngularJS 模板的核心特性,它可以扩展 HTML 的功能。常见的指令有:
(1)ng-repeat
用于循环渲染列表数据。示例如下:
xml
<div ng-controller="myController">
<ul>
<li ng-repeat="item in items">{{item}}</li>
</ul>
</div>
<script>
app.controller('myController', function($scope) {
$scope.items = ['苹果', '香蕉', '橙子'];
});
</script>
这里的ng-repeat指令会遍历$scope.items数组,为每个元素生成一个<li>元素。
(2)ng-if
根据条件决定是否渲染某个元素。示例如下:
ini
<div ng-controller="myController">
<p ng-if="showMessage">这是一条消息。</p>
<button ng-click="toggleMessage()">切换消息显示</button>
</div>
<script>
app.controller('myController', function($scope) {
$scope.showMessage = false;
$scope.toggleMessage = function() {
$scope.showMessage = !$scope.showMessage;
};
});
</script>
当$scope.showMessage为true时,<p>元素才会被渲染。
(3)ng-model
用于实现双向数据绑定,让表单元素的值和$scope中的数据相互关联。示例如下:
xml
<div ng-controller="myController">
<input type="text" ng-model="inputValue">
<p>你输入的内容是:{{inputValue}}</p>
</div>
<script>
app.controller('myController', function($scope) {
$scope.inputValue = '';
});
</script>
3. 过滤器
过滤器用于格式化数据的显示方式。常见的过滤器有currency(货币格式化)、date(日期格式化)等。
bash
<div ng-controller="myController">
<p>价格:{{price | currency:'¥'}}</p>
<p>日期:{{date | date:'yyyy-MM-dd'}}</p>
</div>
<script>
app.controller('myController', function($scope) {
$scope.price = 123.45;
$scope.date = new Date();
});
</script>
这里的currency过滤器将price格式化为货币形式,date过滤器将date格式化为指定的日期格式。
4. 表单控件
模板的加载方式
1. 内联模板
内联模板就是直接将模板代码写在 HTML 文件中。
2. 外部模板
可以将模板代码放在单独的 HTML 文件中,然后通过ng-include指令或路由配置来加载。
ini
<div ng-include="'templates/myTemplate.html'"></div>
优点
- 动态性:能够根据数据的变化动态更新页面内容,提供良好的用户体验。
- 可维护性:将视图和逻辑分离,使代码更易于理解和维护。
- 复用性:可以通过指令和模板的复用,减少代码重复,提高开发效率。
AngularJS 过滤器
在 AngularJS 里,过滤器(Filters)是一种用来格式化数据显示的工具,它能将数据转换为特定的格式,从而更符合用户的展示需求。
定义
过滤器本质上是一个函数,它接收输入数据,对其进行处理后返回处理后的数据。在模板中,可以使用管道符号(|)来应用过滤器。
使用方式
在模板中使用过滤器时,将管道符号(|)置于要过滤的数据之后,接着跟上过滤器名称。若过滤器需要参数,可使用冒号(:)分隔参数。示例如下:
xml
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<title>过滤器使用示例</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular.min.js"></script>
</head>
<body>
<div ng-controller="myController">
<p>{{ price | currency }}</p>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('myController', function($scope) {
$scope.price = 123.45;
});
</script>
</body>
</html>
在这个例子中,{{ price | currency }}将$scope.price的值通过currency过滤器格式化为货币形式。
内置过滤器
AngularJS 提供了多个内置过滤器,以下是一些常见的内置过滤器:
1. currency
用于将数字格式化为货币形式。可以指定货币符号,默认是美元符号$。示例如下:
css
<p>{{ 123.45 | currency:'¥' }}</p>
这会将123.45格式化为¥123.45。
2. date
用于格式化日期对象。可以指定日期格式,例如yyyy-MM-dd、MM/dd/yyyy等。示例如下:
xml
<script>
app.controller('myController', function($scope) {
$scope.now = new Date();
});
</script>
<p>{{ now | date:'yyyy-MM-dd' }}</p>
这会将当前日期格式化为YYYY-MM-DD的形式。
3. uppercase和lowercase
uppercase用于将字符串转换为大写形式,lowercase用于将字符串转换为小写形式。示例如下:
bash
<p>{{ 'hello' | uppercase }}</p>
<p>{{ 'WORLD' | lowercase }}</p>
分别会输出HELLO和world。
4. filter
用于过滤数组,返回满足指定条件的元素。示例如下:
xml
<script>
app.controller('myController', function($scope) {
$scope.items = ['apple', 'banana', 'cherry'];
$scope.searchText = 'a';
});
</script>
<ul>
<li ng-repeat="item in items | filter:searchText">{{ item }}</li>
</ul>
这会显示数组中包含字母a的元素,即apple和banana。
5. orderBy
用于对数组进行排序。可以指定排序的字段和排序顺序(升序或降序)。示例如下:
xml
<script>
app.controller('myController', function($scope) {
$scope.people = [
{ name: 'John', age: 25 },
{ name: 'Jane', age: 20 },
{ name: 'Bob', age: 30 }
];
});
</script>
<ul>
<li ng-repeat="person in people | orderBy:'age'">{{ person.name }} - {{ person.age }}</li>
</ul>
这会按年龄对people数组进行升序排序。
AngularJS中的所有内置过滤器
格式化相关
currency:用于将数字转换为货币格式,可指定货币符号。例如{{ 123.45 | currency:'€' }}会把数字转换为欧元货币格式。date:对日期对象进行格式化,支持多种日期和时间格式。如{{ myDate | date:'yyyy-MM-dd HH:mm:ss' }}。number:把数字转换为带千分位分隔符的字符串,还能指定小数点后的位数。例如{{ 1234.5678 | number:2 }}会保留两位小数并添加千分位分隔符。uppercase:将字符串转换为大写形式,如{{ 'hello' | uppercase }}会输出HELLO。lowercase:将字符串转换为小写形式,如{{ 'WORLD' | lowercase }}会输出world。
数组和对象处理相关
filter:过滤数组或对象,返回满足特定条件的元素。可以使用字符串、对象或函数作为过滤条件。例如ng-repeat="item in items | filter:{name:'John'}"会过滤出name属性为John的元素。orderBy:对数组进行排序,可以指定排序的字段和排序方向(升序或降序)。例如ng-repeat="person in people | orderBy:'age':true"会按age字段降序排列。limitTo:截取数组或字符串的一部分。正数表示从开头截取,负数表示从末尾截取。如{{ [1, 2, 3, 4, 5] | limitTo:3 }}返回[1, 2, 3],{{ 'hello' | limitTo:-3 }}返回llo。json:将对象或数组转换为格式化的 JSON 字符串,常用于调试。例如{{ {key: 'value'} | json }}会输出格式化后的 JSON 字符串。
其他
slice:从数组中提取指定范围的元素,类似于 JavaScript 的Array.prototype.slice方法。例如{{ [1, 2, 3, 4, 5] | slice:1:3 }}返回[2, 3]。orderBy:按照指定规则对数组进行排序。可指定排序的字段以及排序顺序(升序或降序)。例如ng - repeat="item in items | orderBy:'propertyName'"会按照propertyName字段对items数组进行升序排序。filter:根据指定条件过滤数组中的元素。可以使用字符串、对象或函数来定义过滤条件。例如ng - repeat="item in items | filter:'searchText'"会过滤出包含searchText的元素。
自定义过滤器
除了使用内置过滤器,还可以根据需求创建自定义过滤器。自定义过滤器通过angular.module().filter()方法来定义。示例如下:
xml
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<title>自定义过滤器示例</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular.min.js"></script>
</head>
<body>
<div ng-controller="myController">
<p>{{ text | reverse }}</p>
</div>
<script>
var app = angular.module('myApp', []);
app.filter('reverse', function() {
return function(input) {
if (!input) return '';
return input.split('').reverse().join('');
};
});
app.controller('myController', function($scope) {
$scope.text = 'hello';
});
</script>
</body>
</html>
链式使用过滤器
可以将多个过滤器链式使用,依次对数据进行处理。示例如下:
css
<p>{{ 123.456 | number:2 | currency:'¥' }}</p>
这里先使用number过滤器将数字保留两位小数,再使用currency过滤器将其格式化为货币形式。
AngularJS 指令
在 AngularJS 里,指令(Directive)是一种强大的特性,它能对 HTML 进行扩展,让 HTML 拥有动态行为和交互能力。
定义
指令本质上是 AngularJS 编译器在解析 HTML 模板时会识别的特殊属性或元素。当编译器遇到指令时,会根据指令的定义执行相应的操作,比如修改 DOM 结构、绑定事件、实现数据绑定等。
内置指令
1. 数据绑定指令
ng-bind
用于将作用域中的数据绑定到 HTML 元素的文本内容上。和双大括号插值表达式类似,但ng-bind能避免在页面加载时出现闪烁问题。示例如下:
xml
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<title>ng-bind示例</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular.min.js"></script>
</head>
<body>
<div ng-controller="myController">
<p ng-bind="message"></p>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('myController', function($scope) {
$scope.message = '这是一条消息。';
});
</script>
</body>
</html>
ng-model
实现双向数据绑定,让表单元素(如输入框、下拉框等)的值和作用域中的数据相互关联。示例如下:
xml
<div ng-controller="myController">
<input type="text" ng-model="inputValue">
<p>你输入的内容是:{{inputValue}}</p>
</div>
<script>
app.controller('myController', function($scope) {
$scope.inputValue = '';
});
</script>
2. 流程控制指令
ng-repeat
用于循环渲染列表数据。可以遍历数组或对象,为每个元素生成一个 DOM 元素。示例如下:
xml
<div ng-controller="myController">
<ul>
<li ng-repeat="item in items">{{item}}</li>
</ul>
</div>
<script>
app.controller('myController', function($scope) {
$scope.items = ['苹果', '香蕉', '橙子'];
});
</script>
ng-if
根据条件决定是否渲染某个元素。当条件为true时,元素会被渲染到 DOM 中;为false时,元素会从 DOM 中移除。示例如下:
ini
<div ng-controller="myController">
<p ng-if="showMessage">这是一条消息。</p>
<button ng-click="toggleMessage()">切换消息显示</button>
</div>
<script>
app.controller('myController', function($scope) {
$scope.showMessage = false;
$scope.toggleMessage = function() {
$scope.showMessage = !$scope.showMessage;
};
});
</script>
ng-show 和 ng-hide
根据条件控制元素的显示和隐藏。ng - show当条件为true时显示元素,ng - hide当条件为true时隐藏元素。和ng - if不同的是,元素不会从 DOM 中移除,只是通过 CSS 的display属性来控制显示状态。示例如下:
ini
<div ng-controller="myController">
<p ng-show="isVisible">这是可见的消息。</p>
<p ng-hide="isVisible">这是隐藏的消息。</p>
<button ng-click="toggleVisibility()">切换可见性</button>
</div>
<script>
app.controller('myController', function($scope) {
$scope.isVisible = false;
$scope.toggleVisibility = function() {
$scope.isVisible = !$scope.isVisible;
};
});
</script>
ng-switch
根据表达式的值在多个模板中选择一个进行显示。结合 ng-switch-when 和 ng-switch-default 使用。示例如下:
erlang
<div ng-switch="selectedOption">
<div ng-switch-when="option1">选项 1 的内容</div>
<div ng-switch-when="option2">选项 2 的内容</div>
<div ng-switch-default>默认内容</div>
</div>
3. 事件绑定指令
ng-click
绑定点击事件,当元素被点击时,执行指定的表达式或函数。示例如下:
xml
<div ng-controller="myController">
<button ng-click="sayHello()">点击打招呼</button>
</div>
<script>
app.controller('myController', function($scope) {
$scope.sayHello = function() {
alert('你好!');
};
});
</script>
ng-change
绑定表单元素值改变事件,当表单元素的值发生改变时,执行指定的表达式或函数。示例如下:
xml
<div ng-controller="myController">
<input type="text" ng-model="inputValue" ng-change="valueChanged()">
</div>
<script>
app.controller('myController', function($scope) {
$scope.inputValue = '';
$scope.valueChanged = function() {
console.log('输入值已改变:', $scope.inputValue);
};
});
</script>
4. 样式控制指令
ng-class
根据条件动态地添加或移除 CSS 类。有对象语法、数组语法和表达式语法等多种使用方式。示例如下:
ini
<div ng-controller="myController">
<p ng-class="{red: isRed, bold: isBold}">这是一个动态样式的段落。</p>
<button ng-click="toggleRed()">切换红色</button>
<button ng-click="toggleBold()">切换加粗</button>
</div>
<script>
app.controller('myController', function($scope) {
$scope.isRed = false;
$scope.isBold = false;
$scope.toggleRed = function() {
$scope.isRed = !$scope.isRed;
};
$scope.toggleBold = function() {
$scope.isBold = !$scope.isBold;
};
});
</script>
AngularJS中的所有内置指令
数据绑定指令
ng-bind:将作用域中的数据绑定到 HTML 元素的文本内容上,避免插值表达式闪烁问题。例如<span ng-bind="name"></span>。ng-bind-html:将作用域中的 HTML 代码绑定到元素上,会对 HTML 进行转义处理。比如<div ng-bind-html="htmlContent"></div>。ng-bind-template:用于在一个元素内绑定多个表达式,支持使用多个插值表达式。像<span ng-bind-template="{{firstName}} {{lastName}}"></span>。ng-model:实现表单元素和作用域数据的双向绑定,常用于输入框、下拉框等表单元素。例如<input type="text" ng-model="userInput">。
流程控制指令
ng-if:根据条件动态创建或移除 DOM 元素。当条件为true时,元素被添加到 DOM 中;为false时,元素从 DOM 中移除。如<div ng-if="isVisible">可见内容</div>。ng-show:根据条件显示或隐藏元素,通过设置display样式实现,元素仍存在于 DOM 中。例如<p ng-show="showParagraph">显示的段落</p>。ng-hide:与ng-show相反,根据条件隐藏或显示元素。如<p ng-hide="hideParagraph">隐藏的段落</p>。ng-switch:根据表达式的值在多个模板中选择一个进行显示。结合ng-switch-when和ng-switch-default使用。
事件处理指令
ng-click:绑定点击事件,当元素被点击时执行指定的表达式或函数。如<button ng-click="doSomething()">点击我</button>。ng-dblclick:绑定双击事件,元素被双击时触发相应操作。例如<div ng-dblclick="doubleClickAction()">双击此处</div>。ng-mousedown:绑定鼠标按下事件。如<div ng-mousedown="mouseDownHandler()">鼠标按下</div>。ng-mouseup:绑定鼠标松开事件。例如<div ng-mouseup="mouseUpHandler()">鼠标松开</div>。ng-mouseenter:绑定鼠标进入元素事件。如<div ng-mouseenter="mouseEnter()">鼠标进入</div>。ng-mouseleave:绑定鼠标离开元素事件。例如<div ng-mouseleave="mouseLeave()">鼠标离开</div>。ng-mousemove:绑定鼠标在元素内移动事件。如<div ng-mousemove="mouseMove()">鼠标移动</div>。ng-keydown:绑定键盘按键按下事件。例如<input type="text" ng-keydown="keyDown($event)">。ng-keyup:绑定键盘按键松开事件。如<input type="text" ng-keyup="keyUp($event)">。ng-keypress:绑定键盘按键按下并释放事件。例如<input type="text" ng-keypress="keyPress($event)">。ng-change:绑定表单元素值改变事件,常用于输入框、下拉框等。如<input type="text" ng-model="inputValue" ng-change="valueChanged()">。ng-submit:绑定表单提交事件。例如<form ng-submit="submitForm()">...</form>。
样式和类操作指令
ng-class:根据条件动态添加或移除 CSS 类,有对象、数组、表达式等多种语法。如<div ng-class="{active: isActive}">动态类</div>。ng-class-even:与ng-repeat配合使用,为偶数行元素添加指定的 CSS 类。例如<li ng-repeat="item in items" ng-class-even="'even-row'">{{item}}</li>。ng-class-odd:与ng-repeat配合使用,为奇数行元素添加指定的 CSS 类。如<li ng-repeat="item in items" ng-class-odd="'odd-row'">{{item}}</li>。ng-style:根据表达式的值动态设置元素的内联样式。例如<div ng-style="{color: textColor}">动态样式</div>。
表单相关指令
ng-disabled:根据条件禁用表单元素,如按钮、输入框等。例如<button ng-disabled="isDisabled">禁用按钮</button>。ng-readonly:根据条件设置表单元素为只读状态。如<input type="text" ng-readonly="isReadOnly">。ng-required:设置表单元素为必填项。例如<input type="text" ng-model="requiredInput" ng-required="true">。ng-pattern:使用正则表达式验证表单元素的值。如<input type="text" ng-model="email" ng-pattern="/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$/">。ng-minlength:设置表单元素输入值的最小长度。例如<input type="text" ng-model="minLengthInput" ng-minlength="3">。ng-maxlength:设置表单元素输入值的最大长度。如<input type="text" ng-model="maxLengthInput" ng-maxlength="10">。
其他指令
-
ng-app:用于定义 AngularJS 应用的根元素,标记应用的启动点。例如<html ng-app="myApp">。 -
ng-controller:将控制器关联到 HTML 元素上,为元素及其子元素提供作用域和行为。如<div ng-controller="MyController">...</div>。 -
ng-include:用于动态加载外部 HTML 模板文件并插入到当前位置。例如<div ng-include="'template.html'"></div>。 -
ng-pluralize:根据数量值显示不同的复数形式文本。css<ng-pluralize count="itemCount" when="{'0': '没有项目', 'one': '1 个项目', 'other': '{} 个项目'}"> </ng-pluralize> -
ng-transclude:用于在自定义指令中插入外部内容,实现内容的复用。 -
ng-init:在元素作用域中初始化变量,一般不建议大量使用。例如<div ng-init="name='John'">...</div>。
自定义指令
除了使用内置指令,还可以根据需求创建自定义指令。自定义指令通过angular.module().directive()方法来定义。示例如下:
xml
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<title>自定义指令示例</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular.min.js"></script>
</head>
<body>
<div ng-controller="myController">
<my-directive message="这是自定义指令的消息。"></my-directive>
</div>
<script>
var app = angular.module('myApp', []);
app.directive('myDirective', function() {
return {
restrict: 'E',
scope: {
message: '@'
},
template: '<p>{{message}}</p>'
};
});
app.controller('myController', function($scope) {
// 控制器逻辑
});
</script>
</body>
</html>
在这个例子中,定义了一个名为myDirective的自定义指令,它是一个元素指令(restrict: 'E'),通过scope属性接收外部传递的message属性,并在模板中显示该消息。
AngularJS 表单
在 AngularJS 里,表单是实现用户交互的重要组件,它能够收集用户输入的数据,并将这些数据提交到服务器进行处理。
表单的创建
在 AngularJS 中,使用 HTML 的<form>元素来创建表单。可以给表单添加name属性,这样就能在作用域中引用该表单。示例如下:
xml
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<title>AngularJS表单示例</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular.min.js"></script>
</head>
<body>
<div ng-controller="myController">
<form name="myForm">
<label for="username">用户名:</label>
<input type="text" id="username" name="username" ng-model="user.username">
<br>
<label for="password">密码:</label>
<input type="password" id="password" name="password" ng-model="user.password">
<br>
<input type="submit" value="提交">
</form>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('myController', function($scope) {
$scope.user = {};
});
</script>
</body>
</html>
在这个例子中,创建了一个包含用户名和密码输入框的表单,通过ng-model指令将输入框的值绑定到$scope.user对象的相应属性上。
数据绑定
1. 单向数据绑定
使用ng - bind或双大括号插值表达式可以将作用域中的数据显示在表单元素上,但这种方式是单向的,即数据从作用域流向视图。例如:
ini
<p ng-bind="user.username"></p>
2. 双向数据绑定
使用ng - model指令可以实现表单元素和作用域数据的双向绑定。当表单元素的值发生变化时,作用域中的数据也会随之更新;反之亦然。例如:
ini
<input type="text" ng-model="user.username">
表单验证
AngularJS 提供了丰富的表单验证机制,通过内置指令可以方便地对表单元素进行验证。
1. 内置验证指令
ng-required
设置表单元素为必填项。例如:
ini
<input type="text" ng-model="user.username" ng-required="true">
ng-pattern
使用正则表达式验证表单元素的值。例如,验证邮箱格式:
ini
<input type="text" ng-model="user.email" ng-pattern="/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$/">
ng-minlength和ng-maxlength
设置表单元素输入值的最小和最大长度。例如:
ini
<input type="text" ng-model="user.password" ng-minlength="6" ng-maxlength="20">
2. 验证状态
每个表单元素和整个表单都有一些验证状态属性,可以通过这些属性来判断表单或元素的验证状态。常见的验证状态属性有:
$valid:表示表单或元素是否通过验证。$invalid:表示表单或元素是否未通过验证。$dirty:表示表单或元素的值是否被修改过。$pristine:表示表单或元素的值是否未被修改过。$touched:表示表单或元素是否被用户触碰过(如获得过焦点)。$untouched:表示表单或元素是否未被用户触碰过。
可以根据这些验证状态属性来显示相应的错误信息。例如:
ini
<form name="myForm">
<input type="text" name="username" ng-model="user.username" ng-required="true">
<span ng-show="myForm.username.$dirty && myForm.username.$invalid">用户名是必填项。</span>
<input type="submit" value="提交" ng-disabled="myForm.$invalid">
</form>
表单提交
可以使用ng-submit指令来绑定表单的提交事件。当表单提交时,会执行指定的表达式或函数。例如:
xml
<form name="myForm" ng-submit="submitForm()">
<input type="text" ng-model="user.username" ng-required="true">
<input type="submit" value="提交">
</form>
<script>
app.controller('myController', function($scope) {
$scope.user = {};
$scope.submitForm = function() {
if ($scope.myForm.$valid) {
// 表单验证通过,处理提交逻辑
console.log('提交的数据:', $scope.user);
}
};
});
</script>
在这个例子中,当表单提交时,会调用submitForm函数,在函数中会先检查表单的验证状态,如果验证通过,则处理提交逻辑。
AngularJS 组件
在 AngularJS 1.x 版本里,组件是一种较为特殊的指令,它简化了指令的使用方式,提供了更清晰的结构,便于构建可复用的视图部件。
定义与特点
-
定义:组件本质上是一个带有预定义配置的指令,通过特定的语法来定义,专注于封装视图和行为。
-
特点
- 隔离作用域:组件默认使用隔离作用域,能避免与外部作用域产生冲突,提高组件的复用性和可维护性。
- 模板和控制器分离:组件将模板(HTML)和控制器(JavaScript)分离,使代码结构更清晰。
- 绑定策略明确 :使用特定的绑定语法(如
@、=、&)来定义组件与外部作用域之间的数据交互方式。
使用方法
1. 定义组件
使用angular.module().component()方法来定义组件。示例如下:
php
var app = angular.module('myApp', []);
app.component('myComponent', {
templateUrl: 'my - component.html',
bindings: {
message: '@', // 单向字符串绑定
data: '=', // 双向数据绑定
onSubmit: '&' // 绑定函数
},
controller: function() {
var $ctrl = this;
$ctrl.submit = function() {
$ctrl.onSubmit({ data: $ctrl.data });
};
}
});
2. 模板文件(my-component.html)
bash
<div>
<p>{{$ctrl.message}}</p>
<input type="text" ng-model="$ctrl.data">
<button ng-click="$ctrl.submit()">提交</button>
</div>
3. 在 HTML 中使用组件
xml
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<title>AngularJS组件示例</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular.min.js"></script>
</head>
<body>
<div ng-controller="myController">
<my-component message="这是组件消息" data="myData" on-submit="handleSubmit(data)"></my-component>
</div>
<script>
var app = angular.module('myApp', []);
app.component('myComponent', {
templateUrl: 'my-component.html',
bindings: {
message: '@',
data: '=',
onSubmit: '&'
},
controller: function() {
var $ctrl = this;
$ctrl.submit = function() {
$ctrl.onSubmit({ data: $ctrl.data });
};
}
});
app.controller('myController', function($scope) {
$scope.myData = '';
$scope.handleSubmit = function(data) {
console.log('提交的数据:', data);
};
});
</script>
</body>
</html>
绑定策略
@(单向字符串绑定) :用于将外部作用域的字符串值传递给组件。在组件内部,这个值是只读的。例如:<my-component message="这是组件消息"></my-component>,组件内部可以通过$ctrl.message访问这个值。=(双向数据绑定) :用于在组件和外部作用域之间实现双向数据绑定。当组件内部的数据发生变化时,外部作用域的数据也会相应更新;反之亦然。例如:<my-component data="myData"></my-component>,组件内部可以通过$ctrl.data修改和访问这个值。&(绑定函数) :用于将外部作用域的函数传递给组件,组件可以调用这个函数。例如:<my-component on-submit="handleSubmit(data)"></my-component>,组件内部可以通过$ctrl.onSubmit()调用这个函数,并传递参数。
生命周期钩子
组件提供了一些生命周期钩子函数,允许开发者在组件的不同生命周期阶段执行特定的操作。以下是 AngularJS 组件所有生命周期钩子的详细介绍:
1. $onInit()
-
调用时机 :在组件的所有绑定(
bindings)初始化完成之后调用。此阶段,组件的所有输入绑定(@、=、&)都已被正确赋值。 -
用途:通常用于组件的初始化操作,像初始化数据、调用服务获取初始数据等。
-
示例代码:
phpangular.module('myApp', []).component('myComponent', { bindings: { initialData: '<' }, controller: function() { var $ctrl = this; $ctrl.$onInit = function() { // 对初始数据进行处理 $ctrl.processedData = $ctrl.initialData.map(item => item * 2); }; } });
2. $onChanges(changesObj)
-
调用时机:当组件的绑定属性发生变化时会调用该钩子,这里的变化既包括父组件传入的数据改变,也包括在组件内部对绑定属性的修改。在组件初始化时,若绑定属性有初始值,该钩子也会被调用。
-
参数 :
changesObj是一个包含所有变化属性的对象,每个属性对应一个包含currentValue(当前值)、previousValue(前一个值)和isFirstChange(是否为首次变化)的对象。 -
用途:用于响应绑定属性的变化,根据新值更新组件的状态或执行其他操作。
-
示例代码:
phpangular.module('myApp', []).component('myComponent', { bindings: { data: '=' }, controller: function() { var $ctrl = this; $ctrl.$onChanges = function(changesObj) { if (changesObj.data) { if (!changesObj.data.isFirstChange()) { // 处理数据变化 console.log('数据已更新,新值为:', changesObj.data.currentValue); } } }; } });
3. $postLink()
-
调用时机:在组件的 DOM 链接完成之后调用。此时,组件的模板已经被渲染到页面上,并且子组件和指令也已经完成链接。
-
用途:适合进行一些与 DOM 操作相关的初始化工作,比如添加事件监听器、操作 DOM 元素样式等。
-
示例代码:
phpangular.module('myApp', []).component('myComponent', { template: '<button id="myButton">点击我</button>', controller: function($element) { var $ctrl = this; $ctrl.$postLink = function() { // 为按钮添加点击事件监听器 var button = $element.find('button'); button.on('click', function() { console.log('按钮被点击了!'); }); }; } });
4. $onDestroy()
-
调用时机:在组件被销毁之前调用,通常是在组件的 DOM 元素从页面上移除时触发。
-
用途:主要用于清理资源,防止内存泄漏,例如取消定时器、移除事件监听器、关闭网络请求等。
-
示例代码:
phpangular.module('myApp', []).component('myComponent', { controller: function($interval) { var $ctrl = this; var intervalId = $interval(function() { console.log('定时器正在运行...'); }, 1000); $ctrl.$onDestroy = function() { // 取消定时器 $interval.cancel(intervalId); }; } });
5. $doCheck()
-
调用时机 :在每次变更检测循环中调用,变更检测是 AngularJS 用于检查数据是否发生变化并更新视图的机制。该钩子在
$onChanges之后调用。 -
用途:用于实现自定义的变更检测逻辑。当 AngularJS 内置的变更检测机制无法满足需求时,可以在这个钩子中手动检查数据的变化。
-
示例代码:
iniangular.module('myApp', []).component('myComponent', { controller: function() { var $ctrl = this; $ctrl.someData = [1, 2, 3]; var previousData = angular.copy($ctrl.someData); $ctrl.$doCheck = function() { if (!angular.equals($ctrl.someData, previousData)) { // 数据发生了变化 console.log('数据已改变!'); previousData = angular.copy($ctrl.someData); } }; } });
AngularJS 组件路由
AngularJS 的 Component Router 是一个用于单页面应用(SPA)的路由解决方案,它允许开发者根据 URL 的变化动态地加载不同的组件和视图,从而实现页面的切换和导航。
基本概念
- 路由配置:定义了 URL 路径与组件之间的映射关系。当用户访问某个 URL 时,路由器会根据配置找到对应的组件并将其渲染到指定的视图容器中。
- 路由参数 :可以在 URL 中包含参数,用于传递数据给组件。例如,
/users/:id中的:id就是一个路由参数。 - 视图容器 :是一个 HTML 元素,用于显示当前路由对应的组件。通常使用
<ng-outlet>指令来定义视图容器。
配置路由
要使用 Component Router,首先需要引入 ngComponentRouter 模块,并在应用中配置路由。示例如下:
xml
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<title>AngularJS Component Router示例</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-component-router/1.3.3/angular-component-router.js"></script>
</head>
<body>
<a ng-link="['Home']">主页</a>
<a ng-link="['About']">关于</a>
<ng-outlet></ng-outlet>
<script>
var app = angular.module('myApp', ['ngComponentRouter']);
app.value('$routerRootComponent', 'app');
app.component('app', {
template: '<ng-outlet></ng-outlet>',
$routeConfig: [
{ path: '/', name: 'Home', component: 'home', useAsDefault: true },
{ path: '/about', name: 'About', component: 'about' }
]
});
app.component('home', {
template: '<h2>欢迎来到主页</h2>'
});
app.component('about', {
template: '<h2>关于我们</h2>'
});
</script>
</body>
</html>
在这个例子中:
-
引入了
ngComponentRouter模块。 -
使用
$routerRootComponent指定根组件为app。 -
在app组件中,通过
$routeConfig配置路由,定义了两个路由:/路径对应Home路由,使用home组件,并且设置为默认路由。/about路径对应About路由,使用about组件。
路由导航
可以使用 ng-link 指令来创建导航链接,实现路由导航。例如:
css
<a ng-link="['Home']">主页</a>
<a ng-link="['About']">关于</a>
ng-link 指令的参数是一个数组,数组的第一个元素是路由的名称,后面可以跟路由参数。例如:
css
<a ng-link="['User', { id: 1 }]">用户 1</a>
路由参数
可以在路由配置中定义路由参数,然后在组件中获取这些参数。示例如下:
php
app.component('app', {
template: '<ng-outlet></ng-outlet>',
$routeConfig: [
{ path: '/users/:id', name: 'User', component: 'user' }
]
});
app.component('user', {
template: '<h2>用户 ID: {{$ctrl.userId}}</h2>',
controller: function($routerParams) {
var $ctrl = this;
$ctrl.userId = $routerParams.id;
}
});
在这个例子中,/users/:id 定义了一个路由参数 id,在 user 组件的控制器中,通过 $routerParams 服务获取该参数的值。
路由生命周期钩子
Component Router 提供了一些生命周期钩子,允许开发者在路由导航的不同阶段执行特定的操作。以下为你详细介绍所有的路由生命周期钩子:
1. $routerCanActivate(next, prev)
-
调用时机:在路由即将激活之前调用,此钩子可用于决定是否允许路由激活。
-
参数:
next:是一个对象,包含了即将激活的路由信息,像路由参数、路由配置等。prev:是上一个路由的相关信息对象,若没有上一个路由,该参数为null。
-
返回值 :可以返回一个布尔值或者一个 Promise 对象。若返回
true或者 Promise 被解析为true,则允许路由激活;若返回false或者 Promise 被拒绝,则阻止路由激活。 -
用途:常用于实现权限验证、数据预加载等功能。比如,在用户未登录时阻止其访问需要登录权限的页面。
-
示例代码:
phpapp.component('protectedPage', { template: '<h2>这是受保护的页面</h2>', controller: function(AuthService) { var $ctrl = this; $ctrl.$routerCanActivate = function(next, prev) { return AuthService.isLoggedIn(); }; } });
2. $routerOnActivate(next, prev)
-
调用时机:当路由成功激活后调用,此时组件已创建且绑定属性已初始化。
-
参数:
next:包含即将激活的路由信息。prev:包含上一个路由的信息。
-
用途 :可用于初始化组件数据、根据路由参数加载数据等操作。例如,根据路由中的
id参数从服务器获取对应的数据。 -
示例代码:
iniapp.component('userPage', { template: '<h2>用户信息:{{$ctrl.user.name}}</h2>', controller: function($routerParams, UserService) { var $ctrl = this; $ctrl.$routerOnActivate = function(next, prev) { var userId = $routerParams.id; UserService.getUserById(userId).then(function(user) { $ctrl.user = user; }); }; } });
3. $routerOnReuse(next, prev)
-
调用时机:当路由被复用的时候调用。在某些情况下,组件可能不会被销毁,而是被复用,此时会触发该钩子。
-
参数:
next:包含即将激活的路由信息。prev:包含上一个路由的信息。
-
用途:可用于重置组件状态、更新组件数据等。
-
示例代码:
phpapp.component('reusablePage', { template: '<h2>可复用页面</h2>', controller: function() { var $ctrl = this; $ctrl.$routerOnReuse = function(next, prev) { // 重置组件状态 $ctrl.resetState(); }; $ctrl.resetState = function() { // 重置逻辑 }; } });
4. $routerCanDeactivate(next, prev)
-
调用时机:在路由即将失活之前调用,用于决定是否允许路由失活。
-
参数:
next:包含即将激活的下一个路由信息。prev:包含当前即将失活的路由信息。
-
返回值 :可以返回一个布尔值或者一个 Promise 对象。若返回
true或者 Promise 被解析为true,则允许路由失活;若返回false或者 Promise 被拒绝,则阻止路由失活。 -
用途:常用于在用户离开页面时进行数据保存提示、确认操作等。比如,当用户在表单中输入了未保存的数据时,提示用户保存。
-
示例代码:
phpapp.component('formPage', { template: '<form><input type="text" ng-model="$ctrl.inputValue"></form>', controller: function() { var $ctrl = this; $ctrl.inputValue = ''; $ctrl.$routerCanDeactivate = function(next, prev) { if ($ctrl.inputValue) { return confirm('你有未保存的数据,确定要离开吗?'); } return true; }; } });
5. $routerOnDeactivate(next, prev)
-
调用时机:当路由成功失活后调用,此时组件即将被销毁。
-
参数:
next:包含即将激活的下一个路由信息。prev:包含当前即将失活的路由信息。
-
用途:可用于清理资源,如取消定时器、释放内存等操作,以避免内存泄漏。
-
示例代码:
phpapp.component('timerPage', { template: '<h2>定时器页面</h2>', controller: function($interval) { var $ctrl = this; var intervalId = $interval(function() { // 定时操作 }, 1000); $ctrl.$routerOnDeactivate = function(next, prev) { $interval.cancel(intervalId); }; } });
AngularJS Api
AngularJS提供了很多功能丰富的组件,处理核心的ng组件外,还扩展了很多常用的功能组件,如ngRoute(路由),ngAnimate(动画),ngTouch(移动端操作)等,只需要引入相应的头文件,并依赖注入你的工作模块,则可使用。
ng ngRoute ngAnimate ngAria ngResource ngCookies ngTouch ngSanitize ngMock