概述:
适用于以数据操作为主的SPA(Single Page Application)应用。
基于jQuery对传统的DOM操作进行进一步的封装---使用MVC操作代替了所有的DOM操作。
不再是“先查找元素再操作元素”,
所有的操作都是以“业务数据“为中心
搭建环境:
使用 AngularJS 的步骤:
1.引入必需的js文件 : angular.js
2.为父元素声明ngApp属性(这里的父元素一般指html)(系统会自动载入或启动一个NG应用,这个ngApp是唯一的,只能有一个)
3.为父元素内部使用angularJS相关内容
4.
<!DOCTYPE html> <html lang="en" ng-app="haixin"> <head> <meta charset="UTF-8"> <title>ng</title> <!--[if lte IE 9]> <script src="public/js/html5shiv.min.js"></script> <script src="public/js/respond.min.js"></script> <![endif]--> <script src="public/js/jquery-2.2.3.min.js"></script> <script src="public/js/bootstrap.js"></script> <script src="public/js/angular.js"></script> <link rel="stylesheet" href="public/css/bootstrap.css"> <link rel="stylesheet" href="public/css/animation.css"> </head> <body> </body> </html>
ng四大特性:
1.采用MVC模式,页面中再也无需出现DOM操作。
2.双向数据绑定。
3.依赖注入
4.模块化设计
ng四大特性之一MVC模式:
(1)Model: 模型,指业务数据,web项目中由js变量担当model。
(2)View: 视图,用户界面,HTML
(3)Controller: 控制器,Function
ng指令:
AngularJS 中ng模块提供的指令(directive)
(1) ngApp:自动载入/启动一个AngularJS应用
(2) ngInit:用于声明Model(模型)变量
(3) ngController:创建一个控制器对象的实例
(4) ngBind:在当前元素的innerHTML上输入指定的表达式的值
(5) ngRepeat:为HTML增加循环功能,循环输出当前元素
(6) ngIf:为HTML增加选择功能,只有在表达式值为true时,当前元素才添加到DOM树
(7) ngSrc:解决img等标签的src属性中包含{{}}产生的问题
语法: <img ng-src="路径/{{表达式}}"/>
(8) ngClick: 为元素绑定监听函数(不是全局函数,而是Model函数)
语法: <ANY ng-click="模型函数()">
(9) 使用$scope.模型函数名 = function(){}格式来声明模型函数
(10) ngStyle: 赋值为一个Model对象,用于为当前元素指定样式
(11) ngShow/ngHide: 通过display:none/block来控制当前元素是否显示
(12) ngDisabled: 赋值为true/false,可以控制当前元素是否禁用
(13) ngChecked: 赋值为true/false,可以控制当前元素是否选中
Angular中声明变量——Model数据
有两种方式可以声明Model变量:
(1)使用ngInit指令声明
ngInit 指令可以声明为HTML元素的属性或样式
ngInit 指令声明的Model变量可以先使用再声明
ngInit 指令可以一次声明多个Model变量,用分号隔开即可
ngInit 指令可以声明哪些类型的Model变量:
number、string、boolean、对象、数组、对象的数组
注意:使用ngInit定义Model变量时不能使用new关键字;此方法
把View和Model混杂在一起,不推荐使用!
(2)使用Controller创建Model变量——推荐使用
创建Module <= 创建Controller <= 创建Model变量
注意:新版本的Angular要求控制器必须声明在一个模块中!
具体步骤:
1)声明一个自定义的模块(module)
angular.module('模块名', [ ])
2)在当前AngularJS应用中注册自定义模块
ng-app="模块名"
3)在自定义模块中创建Controller函数,其中创建Model数据
$scope.模型变量名 = 值
4)在View中创建Controller对象的实例,指定其作用范围
<标签 ng-controller=“控制器名”>...控制器的有效范围...</标签>
5)在控制器的作用范围内输出Model变量
可以使用{{}}输出Model变量的值开发人员来编写
$scope $rootScope
(1)每个控制器的实例都对应一个作用范围对象,即$scope
(2)在控制器中声明的Model数据,必须保存在一个作用范围内
(3)一个HTML中可以声明多个控制器实例,每个控制器都有自己的作用范围,这些范围内的数据彼此隔离不会互相影响,
可以由不同开发人员来编写
(4)为了在多个控制器间共享数据,可以将Model数据保存在一个“全局作用范围内”——$rootScope——整个AngularApp中
有且只有一个$rootScope对象,且此对象是所有 的$scope的父作用域对象
(5)作用域对象间可以实现继承,只需要将某个控制器实例声明在另一个控制器实例的有效作用域内部即可。
模块:
基本语法:
<script> angular.module("haixin",[]).controller("方法名",function($scope){ $scope.mobile1=""; $scope.mobile2=""; }) </script>
控制器:
定义对象属性:
<script> function studentController($scope){ $scope.student={ stu1:"zhangsan", stu2:"lisi" } } </script>
控制器:
定义方法:
<script> function studentController($scope){ $scope.student={ sName1:"zhangsan", sName2:"lisi", allName:function(){ var n; n=$scope.student; return n.sName1+""+n.sName2; } } } </script>
PS:小练习:
(1)创建一个新的页面,其中声明module、controller、model变量:一个学生对象,其中包含sname、gender、birthday、
score等属性,在view中显示这些model数据
(2)创建一个新的页面,其中声明module、controller、model变量:5个分数组成的数组,在view中的一个列表中输出这5个数字
(3)五个商品的数据显示在View中的table元素中,使用ngRepeat指令进行循环
案例答案:
<html lang="en" ng-app="haixin"> <body> <section ng-controller="practice"> <p>{{obj}}</p> <ul> <li ng-repeat="k in arr">{{k}}</li> <li ng-repeat="(k,v) in arr">{{k}}:{{v}}</li> </ul> </section> <section ng-controller="commodity"> <table class="table table-bordered table-hover text-center"> <th>序号</th><th>商品名字</th> <th>商品价格</th><th>商品图片</th> <tr ng-repeat="i in arr1"> <td>{{$index+1}}</td> <td>{{i.name}}</td> <td>{{i.price}}</td> <td><img ng-src="{{i.img}}" width="60"></td> </tr> </table> <button class="btn btn-block btn-primary" ng-click="add()">点击加载</button> </section> <script> angular.module("haixin",[]).controller("practice",function($scope){ $scope.obj = new Object(); $scope.obj.name = "Tom"; $scope.obj.gender ="boy"; $scope.obj.birthday = "4.18"; $scope.arr=[10,20,30]; }).controller("commodity",function ($scope) { $scope.arr1=[ {name:"商品1",price:"77",img:"images/1.jpg"}, {name:"商品2",price:"33",img:"images/2.jpg"}, {name:"商品3",price:"55",img:"images/3.jpg"} ]; $scope.add=function () { for(var i=0;i<3;i++){ var arr2 ={}; arr2.name="商品"; arr2.price="11"; arr2.img="images/"+(1+i)+".jpg"; $scope.arr1.push(arr2); } } }) </script> </body> </html>
ng四大特性--双向数据绑定:
方向一:把Model数据绑定到View上
把Model数据绑定到View上后,任何Model数据的修改,都会自动更新到View上({{ }}、ngBind、ngRepeat、
ngSrc...都实现了方向1的绑定)
方向二:把View绑定到Model上
把View数据绑定到Model后,任何View数据的修改,都会自动更新到Model上
此后不论任何时候,只要View中的数据一修改,Model中的数据会自动随之修改。实现方法: 只有ngModel指令。
可以使用$scope.$watch(‘模型变量名’, fn)监视一个模型变量值的改变;单行文本输入域、多行文本输入域、下拉框、
单选按钮控件默认会把自己的value属性值绑定到一个Model变量;复选框会把一个true/false值绑定到一个Model变量。
ng模块中提供的服务(service)
(1)$rootScope: 用于在不同的控制器间共享数据
(2)$interval: 提供周期性定时器服务
(3)$interval.cancel(t):清除定时器
(4)$timeout: 提供一次性定时器服务
(5)$http: 发起异步的Ajax请求服务
定时器小案例:input值改变的时候,控制台也会改变,若只写input和P的时候,input值改变的时候P的内容也跟着改变。
代码如下:
<input type="text" ng-model="Uname"> <p>{{name}}</p> <script> $scope.$watch("Uname",function () { console.log($scope.Uname); }) </script>
PS:小练习
1:简易版的点击次数计算器
2:简易版的轮播广告
3:用Bootstrap组件制作一个进度条(每隔0.2s,前进10%)取消定时:$interval.cancel(t);
4:简易版的购物车
5:同意使用条款,则可以注册,否则禁止注册
6:简易版模拟QQ选择切换头像
7:全选或取消全选(PS:4,5,6,7这四个小练习是双向数据绑定了,直接加ng指令就可实现。下面案例中图片
名字一律为n.jpg【n 为正整数】)
案例代码如下:
<html lang="en" ng-app="haixin"> <body> <section class="container"> <section ng-controller="lunbo"> <p>{{n}}</p> <button class="btn btn-danger" ng-click="fn()">点击加一</button><br/> <img ng-src="images/{{img}}.jpg" alt="" width="300"> <button class="btn btn-success" ng-click="prev()">上一个</button> <button class="btn btn-success" ng-click="next()">下一个</button> </section> <section class="progress" ng-controller="jindutiao"> <div class="progress-bar" role="progressbar" aria-valuenow="85" aria-valuemin="0" aria-valuemax="100" ng-style="myStyle"></div> </section> <section ng-controller="a2"> <form> 单价:<input type="number" placeholder="请输入价钱" ng-model="price"> 数量:<input type="number" placeholder="请输入数量" ng-model="num"> 小计:<span>{{price*num}}</span> </form> <input type="checkbox" ng-model="agree">我同意本站的使用条款 <button class="btn btn-success" ng-disabled="!agree">提交注册</button> <button class="btn btn-danger" ng-if="agree">提交注册</button> <button class="btn btn-primary" ng-show="agree">提交注册</button> <select ng-model="pic"> <option value="images/1.jpg">帅锅</option> <option value="images/2.jpg">蕾女</option> <option value="images/3.jpg">大爷</option> <option value="images/4.jpg">大叔</option> </select> <span><img ng-src={{pic}} width="200"></span> <aside> <input type="checkbox" ng-checked="checkAll">A <input type="checkbox" ng-checked="checkAll">B <input type="checkbox" ng-checked="checkAll">C <input type="checkbox" ng-model="checkAll"> <span ng-hide="checkAll">全选</span> <span ng-show="checkAll">取消全选</span> </aside> </section> </section> <script> angular.module("haixin",[]).controller("lunbo",function ($scope) { $scope.n = 10; $scope.fn=function () { $scope.n++; }; $scope.img =1; $scope.next=function () { $scope.img++; if($scope.img==5){ $scope.img=1; } }; $scope.prev=function () { $scope.img--; if($scope.img<1){ $scope.img=4; } } }).controller("jindutiao",function ($scope,$interval) { $scope.n=10; $scope.myStyle={"width":"0%"}; var t = $interval(function () { $scope.myStyle.width=$scope.n+"%"; $scope.n+=10; if($scope.n==90){ $interval.cancel(t); } },200) }) </script> </body>
ng四大特性之—依赖注入:
依赖: Driver对象的创建和运行必需一个car对象,称为Driver对象“依赖于”Car对象。依赖注入体现着“最少知识法则”
依赖对象的解决方法:
(1)主动创建
var c=new Car(); //创建被依赖的对象 var d=new Driver(c); //使用被依赖的对象
(2)被动注入(inject)
一般由特定框架来创建Driver对象,发现其依赖于一个Car对象,框架自动创建被依赖的Car对象——称为“依赖注入”。
依赖注入的典型例子:
angular.module.controller('控制器名', function( $scope, $http ){ })
注意:
控制器对象的构造函数是由AngularJS来调用的,不能手动调用
Angular会根据控制器对象的构造函数的形参名来创建依赖的参数对象——形参名不能随意指定!
若控制器对象未声明形参,则Angular不会传递任何实参进来
控制器对象的形参名(PS:此处的形参名是不能够随意定的)必需是Angular可识别的,但数量和顺序都没有限制—Angular会
根据每一个形参的名称来查找创建被依赖的对象,并自动注入进来。
ng四大特性之—模块化设计:
项目中,可以根据功能的不同,将不同的组件放置在不同的模块中
AngularJS中有两种模块:
(1)AngularJS官方提供的模块:ng、ngRoute、ngAnimate、ngTouch、....
(2)用户自定义的模块:userModule、productModule、orderModule、....
一个NG模块中可以包含多个组件:
(1)controller组件:用于维护模型数据
(2)directive组件:用于在View中输出/绑定Model数据
(3)service组件:用于在不同的控制器中提供某种函数服务
(4)filter组件:用于对View中输出的数据进行格式化
……..
Filter组件 (过滤器):
用于Model数据在View中呈现时进行某种格式的筛选/过滤/格式化。
在View中使用过滤器时,需要借助于管道:|
ng模块中提供的过滤器:(ps:HH指的是24小时制)
(1)lowercase:把数据格式化为小写
(2)uppercase:把数据格式化为大写
(3)number:把数字型数据格式化为三位一个逗号的字符串同时指定小数点位数 eg: {{price | number : 2 }}
(4)currency:把数字型数据格式化为货币格式的字符串,同时指定货币符号 eg: {{price | currency : '¥' }}
(5)date:把数字/Date型数据格式化为特定日期时间格式的字符串
<p>{{name | lowercase}}</p> <p>{{name | uppercase}}</p> <p>{{num | number:2}}</p> <p>{{num | currency:"¥"}}</p> <p>{{time | date:"yyyy年MM月dd日 HH时mm分ss秒"}}</p> <p>{{time | date:"yyyy-MM-dd HH:mm:ss"}}</p>
PS案例:点击一个按钮“加载员工数据”,向服务器发起异步的Ajax请求,获取服务端的一段JSON数据,显示在一个
表格中(注意数据格式);加载完数据后,按钮即禁用/消失。
案例答案:
<!DOCTYPE html> <html ng-app="haixin"> <head lang="en"> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="../css/bootstrap.css"> </head> <body> <section class="container" ng-controller="a1"> <table class="table table-bordered table-hover"> <tr> <th>序号</th> <th>姓名</th> <th>工资</th> <th>入职日期</th> </tr> <tr ng-repeat="j in pro"> <td>{{$index+1}}</td> <td>{{j.ename}}</td> <td>{{j.salary |number}}</td> <td>{{j.hiredate |date:"yyyy年MM月dd日"}}</td> </tr> </table> <button ng-click="add()" class="btn btn-block btn-success" ng-disabled="tab">点击</button> </section> <script src="../js/jquery-1.11.3.js"></script> <script src="../js/bootstrap.js"></script> <script src="../js/angular.js"></script> <script> angular.module("haixin",[]).controller("a1",function ($scope,$http) { $scope.tab = false; $scope.add=function () { $scope.tab = true; $http.get("1.json").success(function (data) { $scope.pro=data; }); } }) </script> </body> </html>
[ {"ename":"Tom", "salary":456765,"hiredate":22224352345}, {"ename":"Mary", "salary":232323,"hiredate":234798237823}, {"ename":"John", "salary":8875645,"hiredate":23423478923}, {"ename":"King", "salary":34325546,"hiredate":772374234333}, {"ename":"Allen", "salary":86756453234,"hiredate":237643274234} ]
Angular官方提供的模块之二——ngRoute模块
ngRoute模块可以让用户自定义“路由字典”,自动解析请求URL中的路由地址,查找路由字典,自动发起异步AJAX请求,把获取的结果放在当前页面中。
值得注意的是,一定要在myApp的moudle中引用ng-route,同时要在文件中引用angular-route.js文件,否则不起作用
Route:路由,为到达目的地而经过的线路
(1)页面URL形如: http://127.0.0.1/index.html#/路由地址
(2)浏览器首先请求基础页面(index.html),再解析URL中的路由地址
(3)查找路由字典,形如:
#/start =》 tpl/start.html
#/main =》 tpl/main.html
....
获取当前URL中路由地址所对应的真实模板页面的地址
(4)客户端发起异步AJAX请求,获取目标模板页面,将服务器返回HTML片段(只含有几个div),插入到当前的DOM树上。
使用ngRoute模块的步骤:
(1)创建唯一完整的页面: index.html,引入angular.js和angular-route.js
(2)在index.html的body中使用ngView指令声明一个容器元素,用于盛放模板页面
(3)创建自定义模块,声明依赖于ng和ngRoute两个模块
(4)在当前模块中使用ngRoute提供的对象配置路由字典
angular.module("haixin",[]).config(function($routeProvider){ $routeProvider.when("/路由地址", { templateUrl:"模板页面URL" }).otherwise({ redirectTo:"/路由地址" }) })
(5)再创建几个模板页面,只需要有div元素即可
(6)测试路由字典的配置是否正确
使用ngRoute模块需要注意的问题:
(1)由于模板页面被客户端请求后挂载在index.htmlDOM树上,所以其中所有的图片等外部资源文件的路径必须相对于index.html,而不是模板页面。
(2)使用ngRoute模块时,无需为模板页面中的某个元素单独设置ngController,只需要在声明路由字典时设置整个模板页面所需要的控制器即可
.when('/路由地址', { templateUrl: 'xxx.html', controller: '控制器名' })
(3)在不同的模板页面间跳转可以采用两种方式:·超链接方式:<a href="#/路由地址"></a>JS编程方式:<button ng-click="jump( )"></button>
$scope.jump = function(){ $location.path('/路由地址'); }
(4) index.html中,由于所有模板页面都是在ngView中切换,ngView外面的内容会始终呈现。
官方提供的模块——ngAnimate
ngAnimate可以支持JS、Transition、Keyframes动画,但它本身未提供任何的动画效果,而是为上面三种技术提供了相应的“动画钩子(Hooks)”
ng模块中提供的指令:ngRepeat, ngInclude, ngIf, ngSwitch, ngShow, ngHide, ngView 和 ngClass默认都提供了动画钩子。
使用ngAnimate模块调用其CSS Transition动画钩子的步骤:
(1) index.html引入angular.js和angular-animate.js。
(2) 自定义模块中声明依赖于ngAnimate模块——特定的指令就会产生动画钩子。
(3) 为ngView声明class,样式中指定transition动画;
可以看到ngAnimate为即将要离开的ngView添加了 ng-leave和ng-leave-active 两个class,为即将要进入的ngView添加了 ng-enter和
ng-enter-active两个class。为这四个class编写特定的样式即可。
(PS:这里只是普通的进出动画,其实可以更炫点,每个页面都有
进出的动画,这个就是后期要研究的,可以充分利用C3一些特效)
.page { transition: all 2s linear; position: absolute; 100%; } /*要离开的ngView元素动画开始时的样式*/ .page.ng-leave { left: 0; } /*要离开的ngView元素动画结束时的样式*/ .page.ng-leave.ng-leave-active { left: -100%; } /*要进入的ngView元素动画开始时的样式*/ .page.ng-enter { left: 100%; top: 100%; transform: scale(0.9); } /*要进入的ngView元素动画结束时的样式*/ .page.ng-enter.ng-enter-active { left: 0; top: 0; }