**AngularJS入门**
AngularJS核心的特性就是:MVC模式、模块化、双向绑定、依赖注入等特性。利用AngularJS,我们能很方便的实现HTML页面和后端的数据交互,让我们逐步脱离JSP页面;HTML+Javascript+AJAX技术让我们能够做出来更轻的Web应用。
<!--more-->
# AngularJS四大特征
## MVC模式
**Model:**数据,相当于angular中的变量($scope.Xxx)(这个变量可以是单一的变量,也可以是实体对象)。
**View:**数据的呈现:HTML+Directive(指令)
**Controller:**操作数据,就是function方法,实现数据的增删改查操作等。
## 双向绑定
AngularJS第二个重要特性就是**双向绑定**,即使用`AngularJS`绑定的变量,能够在`AngularJS`的MVC三层模式中动态的改变。视图层(HTML)绑定的变量传递到控制层(function),控制层能够获取到绑定变量并传递给后端映射进行处理,处理后的数据通过`AngularJS`获取到并仍能够返回到视图层页面,改变原有视图层的数据。
## 依赖注入
Spring中的依赖注入(DI)思想,在`AngularJS`中同样存在。即某个对象依赖的其他对象无需自己手动注入,在该对象创建的时候,起依赖对象就由框架自动创建并注入进来。同后端我们将Service层注入到Controller层,并不需要我们自己手动`new`依赖对象,即由框架帮我们完成了注入。
## 模块化设计
高内聚低耦合法则
1. 官方提供的模块: ng、ngRote、ngAnimate
2. 用户自定义的模块: angular.module('模块名',[])
# 案例
## 表达式
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Angular入门案例</title>
</head>
<body ng-app>
{{1024+1024}}
</body>
<script src="../static/plugins/angular/angular.min.js"></script>
</html>
```
1. 使用`AngularJS`首先要引入angular的JS文件。
2. `AngularJS`的表达式用法就是:`{{表达式}}`,这个表达式也可以是由`AngularJS`绑定的对象。
3. `<body>`中的`ng-app`指令:告诉子元素,以下的其他`AngularJS`指令都会被`AngularJS`识别。
4. `ng-app`指令定义了`AngularJS`应用程序的根元素。
5. `ng-app`指令在网页加载完毕时会自动初始化应用程序。
## 双向绑定
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Angular入门案例</title>
</head>
<body ng-app>
姓名:<input ng-model="name"/><br/>
hello: {{name}}
</body>
<script src="../static/plugins/angular/angular.min.js"></script>
</html>
```
`ng-model`用于绑定变量,被绑定的变量能够在`AngularJS`中动态的改变数据。
**其他指令**
1. `ng-init=""` 用于初始化数据。
2. `ng-click=""` 元素被点击时被触发,可以是一个对应的`AngularJS`控制层方法
3. `ng-controller=""` 用于指定该视图层使用的控制器名称。
4. ...
## 控制器
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Angular入门案例</title>
</head>
<body ng-app="testApp" ng-controller="testController">
a: <input ng-model="a"><br/>
b: <input ng-model="b"><br/>
<button ng-click="test()">计算</button> a+b: {{result}}
</body>
<script src="../static/plugins/angular/angular.min.js"></script>
<script type="text/javascript">
//声明一个testApp模块
var app = angular.module('testApp',[]);
//定义控制器
app.controller('testController',function($scope){
$scope.test = function(){
$scope.result = parseInt($scope.a) + parseInt($scope.b);
}
});
</script>
</html>
```
1. 首先在`<body>`中标识使用的`ng-app`对象和`ng-controller`对象。
2. 使用`angular.module('模块名称',[])`的方式创建`angularJS`的模块对象。
3. 使用`模块名.controller('控制器名',function(){})`的方式定义控制器,写对应的业务代码。同样`模块名.service('服务层名',function(){})`的方式创建服务器。
4. `$scope`使用贯穿了整个`AngularJS`应用,它在`Angular`控制层和视图层建立了一个通道,基于作用域视图在修改数据时会立刻更新`$scope`,同样的`$scope`发生改变时也会立刻重新渲染视图。
## 遍历
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Angular入门案例</title>
</head>
<body ng-app="testApp" ng-controller="testController">
<table>
<tr>
<td>编号</td>
<td>名称</td>
</tr>
<tr ng-repeat="entity in list">
<td>{{entity.id}}</td>
<td>{{entity.name}}</td>
</tr>
</table>
</body>
<script src="../static/plugins/angular/angular.min.js"></script>
<script type="text/javascript">
//声明一个testApp模块
var app = angular.module('testApp',[]);
//定义控制器
app.controller('testController',function($scope){
$scope.list = [{id:1,name:'张珊'}, {id:2,name:'小菜'}];
});
</script>
</html>
```
如上我们使用`ng-repeat`指令即可实现数据的遍历,和JSP中的`<forEach>`标签是不是有些雷同呢?如上其实我们是将需要遍历的数据存入到`AngularJS`绑定的对象`list`中,然后使用`ng-repeat`指令遍历这个对象获取数据。
**注意:** 在`list`对象中定义的数据格式,`AngularJS`本身就规定了你的对象中数据必须是这种格式的(当然你可以使用JSON格式数据),**但是**此处定义的数据并不是标准的JSON格式数据,但是这两种格式数据都能被`AngularJS`识别。
标准的JSON数据格式:
```java
{"id": 1, "name": "张珊"}
```
JSON数据格式规定了其`key`和`value`都必须`""`隔开,使用`''`也不行。
# 代码分层
## 思路
在上面我们一直强调`AngularJS`的MVC设计模式,那么同后端,将对应的代码进行分层不是更方便维护嘛。所以我们将`AngularJS`代码分为三层:
* HTML(视图层):即页面的HTML代码,其中包含了`AngularJS`标识的变量。
* Controller(控制层):即存放主要的业务逻辑的代码(各种function()方法)。
* Service(业务层):这个业务层和我们后端中的业务层不同,因为我们将主要的业务逻辑代码存放到了Controller层,所以这里的`Service`层存放的是和后端交互的请求路径。
即我们通过在HTML(视图层)绑定变量或对象,在Controller中获取到(通过`$scope`获取),调用`Service`层对应的请求路径方法,通过`Controller`层中的请求回调方法(`.success(function(response){})`),获取到请求响应的数据(`response`),然后利用`AngularJS`的双向绑定特性将数据赋值到HTML(视图层)的指定区域。
## 目录结构
如上,为了方便,我将文件都放在一个`test`文件夹中,实际中,我们可以分别建立`service`,`controller`文件夹存放对应的代码。其中:
* `data.json`是我们模拟请求后端而写的`json`格式数据(**注意:**实际中我们后端的请求也要返回`JSON`格式数据)。
* `angular-base.js`存放了创建的`angularJS`模块方法,即`var app = angular.module('模块名',[])`。
* `angular-controller.js`存放`controller`层的逻辑代码,通过`app.controller('控制器名',function(){})`声明。
* `angular-service.js`存放`service`层对应的代码,通过`app.service('业务层名',function(){})`声明。
* `angular-demo.html`视图层,主要是页面实现的代码,其中包含被`angular`绑定的变量,并且这些被绑定的对象需要在`ng-app="模块名"`、`ng-controller="控制器名"`的标识的区域下(父层节点上,通常我们将其定义在`<body>`体中)。
## 模拟的后端相应的数据
**data.json**
```javascript
[
{"id": 1, "name": "涂陌"},
{"id": 2, "name": "TyCoding"},
{"id": 3, "name": "大白"}
]
```
## 自定义angular模块
**angular-base.js**
```javascript
var app = angular.module('baseApp',[]);
```
## 业务层
**angular-service.js**
```javascript
//定义业务层
app.service('testService', function($http){
this.findAll = function(){
return $http.get('data.json');
}
});
```
其中包含了`AngularJS`内置的服务`$http`,可以让我们方便的请求后端,包含`$http.get()`,`$http.post()`等请求方式。
## 控制层
**angular-controller.js**
```javascript
//定义控制器
app.controller('testController', function ($scope, $controller, testService) {
//伪继承
//$controller('baseController',{$scope:$scope});
//获取数据
$scope.findAll = function(){
testService.findAll().success(
function(response){
$scope.list = response;
}
);
}
});
```
1. 在上面我们已经解释了`controller`层声明的方式,就是`app.controller()`方式,其中`function($scope,$controller,testService)`是在此`controller`层需要使用的对象,其中`testService`就体现出了angular的依赖注入思想,`testService`其实是`service`层的名称,当在`controller`中需要使用这个`service`的对象,直接在声明`controller`时就因入其名称即可,angular会自动帮我们将`service`对象注入到`controller`中。
2. 这里我们再注释中添加了伪基层的实现代码。在`AngularJS`中也存在继承的思想,但是仅仅是伪继承,因为可以看到`AngularJS`的继承就是将`baseController`中的`$scope`对象赋值给当前控制器中`$scope`。这样,在当前的控制器中就能使用`baseController`中定义的对象或者方法了。
3. 在调用了`testService`中的方法`findAll()`后,`service`请求相应的数据都存在在回调函数`.success(function(response){})`的`response`中,我们通过`$scope.list`获取到页面中绑定的对象,并将当前相应的数据赋值给`list`中,视图层(HTML)就能通过取JSON格式数据的方式将数据取出来。
## 视图层
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Angular入门案例</title>
</head>
<body ng-app="baseApp" ng-controller="testController" ng-init="findAll()">
<table>
<tr>
<td>编号</td>
<td>名称</td>
</tr>
<tr ng-repeat="entity in list">
<td>{{entity.id}}</td>
<td>{{entity.name}}</td>
</tr>
</table>
</body>
<script src="../static/plugins/angular/angular.min.js"></script>
<script src="../static/plugins/jquery/jquery-3.3.1.min.js"></script>
<script src="../test/angular-base.js"></script>
<script src="../test/angular-service.js"></script>
<script src="../test/angular-controller.js"></script>
</html>
```
在视图层中通过`ng-repeat=""`来遍历后端存储了响应数据的对象`list`,通过`{{entity.id}}`的方式将数据取出来,其实就是取JSON数据的方式,因此我们也必须将请求响应的封装层JSON格式。
这样我们就实现和后端的交互,并将数据回显到了页面上,是不是比JSP要方便快捷很多呢?
## 终
同上上面的学习,我们已经了解到了怎样在HTML页面上利用`AngularJS`完成和后端数据的交互。下面大家来看一下我在实际开发中实现的常见的增删改查的操作:
**页面**
**controller层**
**service层**
**实际效果**
<br/>
# 交流
如果大家有兴趣,欢迎大家加入我的Java交流群:671017003 ,一起交流学习Java技术。博主目前一直在自学JAVA中,技术有限,如果可以,会尽力给大家提供一些帮助,或是一些学习方法,当然群里的大佬都会积极给新手答疑的。所以,别犹豫,快来加入我们吧!
<br/>
# 联系
If you have some questions after you see this article, you can contact me or you can find some info by clicking these links.
- [Blog@TyCoding's blog](http://www.tycoding.cn)
- [GitHub@TyCoding](https://github.com/TyCoding)
- [ZhiHu@TyCoding](https://www.zhihu.com/people/tomo-83-82/activities)