AngularJS
AngularJS基础
AngularJS简介
AngularJS是一个用于构建单页面应用的前端JS框架,在前端践行了MVC设计模式。
AngularJS是一个前端JS框架,或者叫做一个JS库,可以通过script标签的形式引用到HTML页面上。
AngularJS与Angular2以上为两套不同的框架体系
AngularJS是一些以Misko Hevery为首的后端程序员开发出来的前端框架,后被谷歌公司收购并广泛应用于谷歌的各种大小项目。
多页面应用和单页面应用
多页面应用和单页面应用的页面结构对比
一个AngularJS简单应用
第一个AngularJS简单应用
你好,{{name}}
{{1 + 1}}
{{3>2?"3大于2":"3不大于2"}}
ng-app
ng-app用来声明当前页面中angular应用的作用范围, 可以写在包括和
的所有标签上,这时,这个标签和其字标签就都在angular应用的作用范围之内了。
AngularJS核心特性
AngularJS通过 指令 和 字符串模板 将 数据模型(Model) 和 视图(View) 中的对应的数据 双向绑定 。
指令
指令 就是以 ng- 开头的一些扩展HTML标签属性,比如 ng-app 、ng-model 。在标签上使用指令,就可以让标签具有一些AngularJS提供的功能。
字符串模板
字符串模板 就是以被 {{}} 包含的一些 AngularJS表达式 , AngularJS表达式 包括JS表达式和AngularJS专有的特殊表达式。
双向绑定
当 视图(View) 上显示的内容发生变化时,数据模型(Model) 中相应的变量会随之变化。
当 数据模型(Model) 中的变量发生变化时,视图(View) 上显示的内容会随之变化。
MVC设计模式
MVC设计模式说明
第一个AngularJS正式应用
第一个AngularJS正式应用
{{mc.name}}
angular.module
用于创建或者获取指定的angular应用。
//创建: angular.moudle("ng-app的值,即应用的名字",["配置信息"]);
angular.module("myApp",[]);//注:即使没有配置信息,也要写一个空数组
//获取: angular.moudle("ng-app的值,即应用的名字");
angular.module("myApp");
controller
用于向应用添加控制器。
//myApp.controller("控制器名字",构造函数);
myApp.controller("myCtrl",function(){
//为了避免this指向改变造成的问题并且使用起来更加方便,将this转存
var mc = this;
mc.属性名 = 值;
mc.函数名 = function(){
};
});
AngularJS应用程序开发步骤
1、引用AngularJS库。
2、ng-app、ng-controller。
3、创建应用程序、添加控制器。
4、双向绑定。
AngularJS初级语法
使用ng-repeat展示数组中的数据
语法:
<标签 ng-repeat="引用 in 数组">{{引用}}标签>
<标签 ng-repeat="引用 in 数组">{{引用.属性}}标签>
展示简单数组
- {{i}}
展示对象的数组
序号
用户名
年龄
{{$index + 1}}
{{u.name}}
{{u.age}}
展示简单数组时的注意事项
当简单数组中有两个 等价 (类似于===,但是NaN等价于NaN)的元素时,需要track by 每次遍历时唯一的值以进行区别。
- {{i}}
ng-repeat中的其他特殊属性**
在ng-repeat中,除了$index是常用的number型特殊属性外,还有5种boolean型的特殊变量供我们使用。
特殊属性 | 为true条件 |
---|---|
$first | 遍历时的第一个(即下标为0) |
$last | 遍历时的最后一个(即下标为length-1) |
$odd | 下标为奇数的(注意下标从0开始,即传统意义上的偶数) |
$even | 下标为偶数的(注意下标从0开始,即传统意义上的奇数) |
$middle | 遍历时除了第一个和最后一个(0 < 下标 < length - 1) |
根据条件展示
AngularJS可以根据某个表达式的结果决定某部分内容是否显示。这种特性在许多场景下都有重要应用,常见的是用于在服务器端数据未加载完成时显示提示信息。
AngularJS用了两种不同的方式来实现这一特性。
- 根据表达式的结果,决定是否动态创建这个DOM元素: ng-if 和 ng-switch 。
- 根据表达式的结果,决定是否显示这个标签: ng-show 和 ng-hide 。
两种方式比较
- 动态创建DOM的效率比修改标签显示方式的效率低很多。
- 动态创建DOM的方式能避免极个别情况下的样式错误或逻辑错误。
因此需要根据使用场景来决定采取何种方式。
ng-if
语法:
<标签 ng-if="布尔表达式">标签>
例子:
ng-if 1
ng-if 2
ng-if 3
ng-switch
语法:
<标签 ng-switch="表达式">
<标签 ng-switch-when="值1">标签>
<标签 ng-switch-when="值2">标签>
<标签 ng-switch-default>标签>
标签>
例子:
1
2
默认
ng-show
语法:
<标签 ng-show="布尔表达式">标签>
例子:
ng-show 1
ng-show 2
ng-show 3
ng-hide**
ng-show的反逻辑,即为true不显示,为false显示。不常用。
特殊属性绑定
ng-src和ng-href
ng-src 用于代替图片的src属性,用于防止数据加载完毕前的错误图像显示。
ng-href 用于代替链接的href属性,用于防止数据加载完毕前的错误链接指向。
ng-class
ng-class 可以使用扩展的AngularJS表达式来更加智能的动态控制标签样式。包括单值语法、数组语法和对象语法。
单值语法
<标签 ng-class="某个属性">标签>
数组语法
<标签 ng-class="[属性1,属性2]">标签>
对象语法
<标签 ng-class="{'样式名称1':布尔表达式1,'样式名称2':布尔表达式2}">标签>
绑定表单元素
ng-model 可以双向绑定表单元素。
普通文本框
单选框
1
2
3
{{mc.r}}
多 选框
注意:对于多选框,ng-model只能绑定其checked属性(true或false。 因此,如果想要进行默认选中,一般需要使用另一个指令 ng-checked ;并且,多个选择框不要使用同样的ng-model值,否则会发生联动。
由于这种特性,故多选框不适合用来做表单提交,多用于结合ng-if或ng-show来做出选中时显示额外内容的效果。
A
B
C
mc.c1:{{mc.c1}}
mc.c2:{{mc.c2}}
mc.c3:{{mc.c3}}
下拉列表框
- 当option标签没有value属性时,ng-model和标签体绑定,取值和默认赋值依据标签体进行。
- 当option标签有value属性时,ng-model和value属性绑定,取值和默认赋值依据value属性进行。
{{mc.s1}}
{{mc.s2}}
AngularJS对事件的封装
绑定到控制器属性中的函数,除了可以在控制器中直接调用外,更多的应用是作为事件的处理函数。使用AngularJS封装的事件(也是一种AngularJS指令),可以直接处理AngularJS管理的各种动态数据。
例子:
- {{txt}}
AngularJS事件型指令列表
事件(指令) | 触发时机 | 触发元素 |
---|---|---|
ng-click | 鼠标单击 | 任意标签 |
ng-dblclick | 鼠标双击 | 任意标签 |
ng-mouseenter | 鼠标移入 | 任意标签 |
ng-mouseleave | 鼠标移出 | 任意标签 |
ng-mousemove | 鼠标移动 | 任意标签 |
ng-change | 表单元素中用户输入的数据每次被改变 | 表单元素 |
ng-copy | 在多种情况下触发,包括复制、选中等 | 表单元素 |
ng-cut | 表单元素中用户输入的数据每次被剪切 | 表单元素 |
ng-paste | 表单元素中用户输入的数据每次被粘贴 | 表单元素 |
ng-focus | 表单元素每次获得焦点 | 表单元素 |
ng-blur | 表单元素每次失去焦点 | 表单元素 |
注:ng-change必须配合ng-model使用。
AngularJS中级语法
AngularJS的代码侵入性比较强,很难兼容于类似于jQuery之类的其他前端框架。故不能使用jQuery来操作AngularJS中管理的数据。
依赖注入简介
依赖注入(Dependency Injection,简称DI)是指一个功能需的一些功能组件(对象、函数等)不是由这个功能本身创建,而是由其他功能创建。前者无需关心这一功能组件的实现。
最简单的依赖注入的例子就是调用函数时传参:函数无需关心传入的参数是如何得来的,只需要声明这个参数,就可以直接使用。
服务
服务 在AngularJS中是一个函数或一个对象,它可以依赖注入到任何需要使用它的控制器中。
AngularJS提供的服务以$开头。常用的有 $timeout、$interval 、$scope、$rootScope和$http。
$timeout和$interval
在AngularJS中,不能直接使用setTimeout和setInterval来操作AngularJS中的动态变量。 如果需要类似这样的功能,需要使用AngularJS的$timeout和$interval服务。
例子:
{{mc.test}}
解决代码压缩引发的依赖注入的问题
由于依赖注入是根据声明自动注入的,因此要求形参的名字必须完全一致。然而js代码经过压缩后,会自动变更形参的名字,使得注入失效。AngularJS也针对这种情况提出来一种新的写法, 当我们使用依赖注入时,务必要采取这种写法 。
写一个数组,将被注入的函数为数组的最后一个元素。将注入的服务写成形参的同时以字符串的形式作为数组的前几个元素, 并且这几个字符串和形参保持顺序一致 。
如上例可以写成这样:
{{mc.test}}
$scope**
$scope是作用域,每个controller都有一个作用域,ng-repeat等一些比较特殊的指令也会创建新的子作用域,ng-model和ng-init也可以直接把一些数据直接绑定到作用域中。 ** 在一些比较大的AngularJS项目中,作用域的关系错综复杂,因此不建议大家使用$scope和ng-init。**
例子:
{{name}}
$rootScope
$rootScope也是作用域,不过是每个app有且只有一个的 根作用域 ,由于在每个控制器中都能访问这唯一的一个作用域,因此可以用来跨控制器传值。
例子:
{{text}}
$http
$http是AngularJS对ajax的封装,用来向服务器发送请求。
GET请求
"use strict"
var myApp = angular.module("myApp",[]);
myApp.controller("myCtrl",["$http",function($http){
var mc = this;
$http({
url:"http://127.0.0.1/param?name=lins&age=24",
method:"GET"
}).then(function(resp){
//成功时的回调函数
//resp.data就是服务器以json形式发送的对象
console.log(resp.data);
//服务器返回的数据可以交给AngularJS进行管理,以便在页面上渲染
mc.users = resp.data;
},function(err){
//失败时的回调函数
});
}]);
POST请求
"use strict"
var myApp = angular.module("myApp",[]);
myApp.controller("myCtrl",["$http",function($http){
var mc = this;
$http({
url:"http://127.0.0.1/httpServer/param",
method:"POST",
data:"name=lins&age=24",
//配置请求方式为模拟表单
headers:{"Content-Type":"application/x-www-form-urlencoded"}
}).then(function(resp){
console.log(resp.data);
mc.users = resp.data;
},function(err){
//失败时的回调函数
});
}]);
从页面收集参数**
从页面收集参数
用户名:
密码:
性别:
男
女
过滤器
有时,我们想要某些数据,在显示到页面上之前进行统一处理。这时,再依赖控制器实现,往往过于繁琐。AngularJS为了解决这种问题,提出了过滤器的概念。
货币格式过滤器currency
{{mc.c1 | currency}}
{{mc.c2 | currency:"¥"}}
{{mc.c3 | currency:"$":4}}
在JS中使用过滤器
过滤器的一般用法是在页面上(视图层)直接使用,同时,它也可以作为一种服务注入到控制器中使用。
"use strict"
var myApp = angular.module("myApp",[]);
myApp.controller("myCtrl",function($filter){
//语法:$filter("过滤器名字")(要过滤的数据,参数1,参数2,...)
console.log($filter("currency")(15,"¥",3));
});
日期格式过滤器
{{mc.now | date:"yyyy-MM-dd HH:mm:ss"}}
数组排序过滤器
- {{i}}
- {{i}}
姓名
年龄
{{u.name}}
{{u.age}}
姓名
年龄
{{u.name}}
{{u.age}}
数组查找过滤器
- {{i}}
姓名
年龄
{{u.name}} {{u.age}}
自定义过滤器
有时,AngularJS提供的过滤器并不能满足我们的需求。这时,我们就可以自定义过滤器。
{{mc.test | price}}
AngularJS高级语法
路由
路由描述了url和视图的映射关系。
AngularJS对路由的实现
AngularJS的路由系统,由一个主页面和若干个子页面构成。所有的JS代码和CSS代码放在主页面上,子页面仅仅完成制作视图的功能。
AngularJS对路由的实现是通过URL HASH实现的,根据访问地址中的HASH部分,唯一的确定一个子页面,并使用AJAX的方式将子页面中的内容拉取到主页面上的某个局部进行展示。
主页面的制作步骤:
- 定义ng-app。
- 定义子页面的显示区域 ui-view 。
- 配置路由规则。
- 完成控制器的制作。
子页面的制作步骤:
- 绘制视图。
基本路由
主页面:
基本路由主页面
route1.html:
这是路由1的页面
route2.html:
这是路由2的页面
{{c2.test}}
样式控制
ui-sref-active 是一个根据当前路由子页面控制样式的属性,属性值是一个class。它可以被加在含有ui-sref属性的标签或者其父标签上。 当用户切换到对应的路由时,ui-sref-active所在的标签会被加入其属性值所对应的class 。
动态路由(路由传参)
AngularJS中的路由传参是利用url传参,因此主要是在url相关部分进行配置。
动态路由配置步骤:
- 在路由规则中的url部分使用
/:
指定参数的名字。 比如配置为url:"/user/:name/:age"
,那么当我们访问“/user/lins/18”时,“lins”就会被赋值到name中,18就会被赋值到age中。 - 在ui-sref中进行参数传递。 语法:
链接文本
。
下面的例子模拟了一个用户查询:在主页面将一个固定的用户id传递到user页面展示出来,在home页面(首页)将要查询用户的id传递到user页面展示出来。
主页面:
Title
home页面:
user页面:
这是用户详情页
这是id为{{uc.id}}的用户的用户详情
补充
多页面应用和单页面应用的详细对比
多页面应用
组成一个应用的每个页面,几乎是相互独立的。在加载每张页面时,仅仅加载这个页面所需的CSS和JS。
优点:
- 进行首次页面加载时仅需加载这个页面所需资源,因此速度较快。
- 因为页面是完整的从服务器传送到客户端,因此便于搜索引擎抓取。
- 自动实现“前进”和“后退”的功能。
缺点:
- 进行页面跳转时,整张页面从零开始加载,耗时较长。
- WEB浏览器和手机APP需要两套不同的后端代码,不利于前后端分离。
单页面应用
整个应用仅有一个主页面。在加载主页面时,加载全部所需CSS和JS;在进行页面切换时,无需重新加载CSS和JS。
优点:
- 在首次页面加载完成后,页面切换效率较高,有较好的用户体验。
- WEB浏览器和手机APP需要的后段代码几乎完全相同,可以较好的实现前后端分离。
缺点:
- 页面首次加载耗时较多,因此必须进行JS和CSS压缩来缓解。
- 服务器到客户端的通信是不连续的,不利于搜索引擎抓取。
- 需要利用URL HASH和页面栈等技术实现“前进”和“后退”的功能。