1、什么是AngularJS
AngularJS是一个开源的JS框架,目标是做SPA,适用在数据绑定操作比较频繁的场景
2、AngularJS的四大特征
①采用了MVC的设计模式
Model 数据
View 视图
Controller 控制器
MVC的工作原理:在view进行了交互,会通过控制器中的方法对数据增删改查相关的操作。
优势:
MVC的优势在于将数据和视图隔离开,解耦
②双向数据绑定
方向1:将数据绑定到视图
方向2:将视图中用户操作的结果绑定到数据
③依赖注入
将依赖的组件或者模块,直接注入到当前的对象,就可以直接拿来用
④模块化设计
封装和重用
表达式、常用指令
<any>{{表达式}}</any>
ng-app ngApp指令
使用这个指令自动载入启动一个AngularJS应用
ngApp指令设计为应用的根元素,一般把它放在页面的根元素附近。如<body> <html>标签
ngInit指令
ng-init指令允许声明变量,需要注意:为双向绑定
用法:
<any ng-init="name='zhangsan;age=20'"></any>
ng-init 声明变量时,无需写var,多个变量赋值表达式用分号
ngBind
ngBind 指令将制定的表达式的值输出为当前元素的innerHTML
用法:
<any ng-bind="表达式"></any>
作用:告诉Angular使用所给表达式的值替换指定HTML元素的文本内容
ngRepeat
作用:给html添加循环结构的支持
<any ng-repeat="临时变量名 in 集合名称"></any>
<any ng-repeat="(key,value) in 集合名称"></any>
注意事项:如果遍历数组时,有重复的数据,会报错的,解决方案track by $index
ngIf 指令
作用:根据ngIf表达式的结果 选择节点是不是要挂载到DOM,如果结果为真,就挂载,结果为假,就从DOM中移除掉。
ngSrc 指令
<img ng-src="img/{{imgUrl}}"></img>
注意事项:
将src ---> ngSrc;
路径要加上双花括号去取值
ngShow/ngHide 显示和隐藏
ngShow="表达式" 表达式结果为真,就显示,为假就隐藏
ngHide="表达式" 表达式结果为真,就隐藏,为假就显示
如何通过angularJS实现mvc?
①认识MVC
为什么出现MV*?
①移动互联网时代,对于网页的要求是越来越高的
代码规模越来越大,切分职责
②封装和重用
③为了后期的维护和迭代
什么是MVC?
Model 数据
View 视图
Controller 控制器
②工作原理:
在view进行了交互,会通过控制器中的方法对数据增删改查相关的操作,由于数据和视图是相互隔离的,有数据绑定的。
③通过ng来实现mvc的基本步骤:
1、创建模块
var app = angular.module('模块名称',['moduleA','moduleB'])
2、调用模块
ng-app='模块名'
3、创建控制器
app.controller('控制器名称',func)
4、调用控制器
ng-controller="控制器名称"
创建数据
$scope 是建立起数据和视图的桥梁,将数据定义在$scope对象中,在视图中就可以直接引用对象中定义的变量
在控制器的$scope中定义的变量,要想在视图中去调用,必须在控制器的范围内。
将数据绑定到视图显示
双花括号
自定义指令
1、指令的创建方法:
var app = angular.module();
app.directive('指令的名称',func);
2、指令的使用方法:
涉及到命名规则,指令本身命名要符合驼峰式写法,一般有两部分构成,前缀(项目或者模块的简写)和后缀(指令的作用),在使用时 要遵循烤串式
案例:
app.directive('tsHello',func)
ts-hello
3、指令的其它特性
restrict:‘EC’
E:element
A:attribute
C:class
M:comment
replace:true/false
将调用指令的元素替换掉
div ts-hello
template:指定模板内容
scope:存储数据
自定义指令传参
①指令内部设置允许接收参数
scope:对象
app.directive('tsHello', function () {
return {
template: "<h1>{{testName}}</h1>",
scope:{
// @ 指定要从调用指令的属性中 找到test-name对应的值 赋值给testName
testName:'@'
}
}
})
②调用指令时 把参数发送过去
<ts-hello test-name="参数"></ts-hello>
双向数据绑定
方向1: 将数据 绑定 视图
绑定的方式:
①ng中常用指令 ngRepeat..
②双花括号
方向2:将视图中用户操作的结果 绑定 数据
1、绑定的方式:
ngModel
用法: <input ng-model='变量名称'></input>
作用:将每一次的输入都保存在指定的变量中
2、属于$scope的$watch,可以用来监听数据的变化
$scope.$watch(
'keyword',
function(newValue,oldValue){
})
指令:ngOptions 动态的生成多个option
select ng-options="color.name for color in array"
过滤器、函数
1、过滤器的概述
过滤器:对数据进行筛选、过滤、格式化
过滤器使用语法:是支持多重过滤的。
{{表达式 | 过滤器:参数 | 过滤器}}
2、常用过滤器
currency 货币样式
date 日期
orderBy 排序(降序或者升序)
limitTo 限定显示的元素的个数(数组)
uppercase/lowercase 大小写的转换
3、自定义过滤器
自定义过滤器的本质 就是定义一个方法(有参数和右返回值)
var app = angular.module()
app.filter('过滤器名称',function(){
return function(inputValue,arg1。。){
return '处理后的数据'
}
});
4、常用函数
angular.toJson/fromJson:
json格式的序列化(将一个对象或者数组序列化为json格式的字符串)、反序列化(..)
angular.forEach(集合名称,function(value,key){})
angular.uppercase/lowercase
四、服务
服务的本质在ng中 就是一个对象,可以提供数据和方法。
服务有很多:
$location/$http/$scope/$rootScope/$window/$interval/$timeout...
服务的用法:
只需要在对应的ng对象中注入对应的服务,可以在ng对象中调用服务中封装好的方法和数据了
app.controller('myCtrl',function($location,$scope){
//调用服务中封装好的方法、数据
})
$scope和$rootScope的关系
①每一个控制器对应的有一个$scope,每一个$scope都是相互隔离的
②$scope的id是根据控制器的加载顺序是递增的,有共同的父元素$rootScope
控制器之间数据如何传输?
①可以把要共享的数据或者方法 放在$rootScope
在子对象中 可以 读取 父对象中的数据或者方法
②借助于控制器之间的嵌套
div ng-controller='myCtrl02'
div ng-controller='myCtrl03'
③借助于事件
事件的绑定:
$scope.$on('eventName',function(event,data){
})
事件的触发
//由父向子 触发
$scope.$broadcast('eventName',data);
//由子向父 触发
$scope.$emit('eventName',data)
一、ng常用的内置服务
$scope $location $rootSCope $interval $timeout $http...
数据绑定的工作原理:
每一次完成数据的绑定,在ng框架的背后 都会watcher, 监听数据的变化,如果发生了变化就会更新DOM。
如果检测数据的变化??ng在初始化之后,会有一个循环,在不断的判断数据的变化,将这个循环称之为$digest循环。
什么需要手工执行$scope.$digest()?
有冲突的时候,发现数据变化 没有引起DOM的更新
除了$digest(),有时还会使用$scope.$apply();
不同点在于$apply会触发$rootScope所有的子作用域对象的$digest循环。
1、$interval $timeout
var promise = $interval(func,delay) 开启一个周期性定时器
$interval.cancel(promise) 取消一个周期性定时器
var promise = $timeout() 开启一个定时器
$timeout.cancel(promise) 取消一个定时器
2、$http 处理网络请求
发起get请求:
$http({method:'get',url:''}).success().error()
$http.get('url').success().error()
发起post请求:
$http.post(‘url’,data).success().error()
$http({method:'post',url:''}).success().error()
//如果post请求需要传参:
app.run(
function ($http) {
$http.defaults.headers.post = {'Content-Type':'application/x-www-form-urlencoded'};
})
//实现表单的序列化
var result = $httpParamSerizlizerJQLike(对象);
//key1=value1&key2=value
二、ng自定义服务
1、factory方法
创建的方式:
var app = angular.module();
app.factory('服务名称',function(){
return {
key:value,
funcName:func
}
})
使用的方式:
和内置服务用法是一样的
2、service 方法
app.controller/filter/module/service..
创建服务的方式:
app.service('服务名称',构造函数);
使用服务的方式:
就像是使用内置的服务,引入到ng对象中就可以了
3、const/value
创建时一些常量或者变量服务
app.constant('服务名称',{})//常量
app.value('服务名称',{})//变量
总结:factory 必须要求有一个返回值
service 指定的构造函数 constant 创建的常量服务 value变量服务
三、依赖注入
依赖注入:将需要用到的对象或者服务 直接注入到对应的ng对象(服务,控制器..),直接去使用,不用理会要注入的对象内部是怎么实现的。
文件压缩: yui-compressor uglify..
文件压缩:删除注释、没有语义的空白字符,同时做了代码的混淆($scope -> a 这是对于代码的保护同时也是一种压缩)
之前的服务注入的方式 在进行文件压缩之后,是无法找到对应的服务。
考虑到在进行文件压缩时,字符串或者数组是不会发生变化的,从这里找到切入点。
依赖注入:
①推断式(猜测式)
app.controller('myCtrl',function(服务1名称){
})
②标记式
将依赖的各个服务的名称放到一个数组中作为依赖注入的标记,即使压缩之后,我们依然可以通过数组中的服务名称找到对应 的服务,提供给我们去使用。
//通过一个数组对依赖的服务做标记
funcHandler.$inject = ['$scope','$show'];
由于标记式的写法是依赖一个字符串的数组,所以服务是有先后顺序的:在$inject中数组中服务的顺序要和控制器处理函数引入服务的顺序是要一致的
funcHandler = function($scope,$show)
③行内式(内联式)
要求在创建一个ng对象时,第二个参数可以是一个数组,数组中存储的是服务的名称,最后一个必须是ng对象对应的处理函数
app.controller('myCtrl',
['$scope','$print',function($scope,$print){}]);
注意事项:最后一个元素必须是方法,而且服务的名称在数组中和在方法的顺序要保持一致。
要求:注入服务,统一使用行内式依赖注入。
进阶知识:注入器($injector)
在ng启动的时候,就已经被初始化了,提供了常用的API(application interface 应用程序接口),有两个经常用到的方法:
has() 判断一个服务是否存在
get ('$show') 得到一个指定的服务的对象
一、模块化设计
一个ng的模块都可以包含哪些?
控制器
directive(自定义指令)
服务(自定义服务)
过滤器(自定义过滤器)
方法、对象。。
ng的四大特征:
MVC/双向数据绑定/依赖注入/模块化设计
封装、重用:
提高开发速度 降低测试难度 提高代码的复用率
模块之间相互调用:
userModule settingModule
如果settingModule要想调用userModule中的服务或者自定义的过滤器、指令等,只需要指定依赖于userModules
二、ngRoute模块
ng的定位:实现SPA(single page application),适用于数据操作比较频繁。
1、SPA的工作原理:
①在地址栏输入
http://127.0.0.1/index.html/#路由地址
②解析完整的页面地址 、 路由地址
③从路由词典的配置对象 读取 该路由地址对应的 路由信息
④在路由信息中得到该路由地址对应的模板(代码片段)页面地址,发起ajax请求
⑤将请求到的模板页面 插入 到容器 给用户呈现出来
2、通过ngRoute来实现一个SPA的基本步骤:
①创建一个完整的html页面
引入angular-route.js,在创建自定义模块时指
<script src="js/angular-route.js"></script>
angular.module('myApp',['ng','ngRoute']);
②创建一个容器来盛放代码片段
ngView指定盛放代码片段的容器
③创建应用程序需要的代码片段
④配置路由词典
when/otherwise
app.config(function($routeProvider){
$routeProvider
.when()//添加一条路由信息
.otherwise() //处理当前的路由地址不是配置的任何一个时,一般都是直接重定向
})
3、SPA如何来实现跳转
①直接修改地址栏中的url
②a <a href="#路由地址"></a>
③js $location.path
练习:通过ngRoute来创建一个SPA,有三个代码片段,分别是myLogin myRegister myMain
myLogin: 注册按钮(跳转到注册) 登录超链接(跳转到主页面)
myRegister: '完成注册,去登录'按钮 (跳转到登录页面)
myMain: 退出登录超链接 (跳转到登录页面)
4、跳转的同时传递参数
①搞清楚 发送方 接收方
②接收方做点准备
when('/main',{})
--> when('/main/:id',{})
③接收传过来的数据
$routeParams 服务(服务的本质是对象)
④发送参数
a href='#/myDetail/2'
$location.path('/myDetail/2')
demo:
创建一个SPA,两个代码片段:list detail,点击list中的列表项,跳转到detail,同时将该列表项的下标发给detail;detail接收到传递过来的参数 显示在详情页面
案例1 双向数据绑定
<div ng-controller="myCtrl">
<select ng-model="img1"> //方向2
<option value="1.jpg">郁金花</option>
<option value="2.jpg">水仙花</option>
<option value="3.jpg">月季花</option>
</select>
<img ng-src="img/{{imgh}}" /> //方向1
<select ng-model="city" ng-options="city.name for city"></select>
</div>
<script>
var app = angular.module('mymodule',['ng']);
app.controller('myCtrl',['$scope',function($scope){
$scope.img1 = "1.jpg"; //设置默认值
$scope.cityList = [
{name:"北京",value:"bj"},
{name:"上海",value:"sh"},
{name:"广州",value:"gz"}
];
$scope.city = $scope.cityList[1]; //设置默认值
}])
</script>
案例2 $watch
<div ng-controller="myCtrl">
<input type="text" ng-model="keyword" /> //方向2
<h1>{{keyword}}</h1> //方向1
</div>
<script>
var app = angular.module('mymodule',['ng']);
app.controller('myCtrl',['$scope',function($scope){
$scope.keyword = "";
//第一个参数:要监听的数据名称
//第二个参数:监听数据变化时,要执行的操作
$scope.$watch('keyword',function(newValue,oldValue){
//当模型数据keyword发生变化,要执行的处理函数
console.log($scope.keyword);
})
}])
</script>
//注册
<input type="checkbox" ng-model="isAge" />是否同意
<br />
<button ng-disable="!isAge">注册</button>
案例3 过滤器
<div ng-controller="myCtrl">
<table>
<thead>
<tr>
<th>姓名</th>
<th>年龄</th>
<th>性别</th>
<th>成绩</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="tmp in student | orderBy:'score':true | limitTo: 3"></tr>
<td ng-repeat="stu in tmp">{{stu}}</td>
</tbody>
</table>
</div>
<script>
var app = angular.module('mymodule',['ng']);
app.controller('myCtrl',['$scope',function($scope){
$scope.student = [
{name:"lilei",age:18,score:100},
{name:"lilei2",age:19,score:99},
{name:"lilei3",age:20,score:98},
{name:"lilei4",age:21,score:97},
]
}])
</script>
案例4 全选/取消全选
<div ng-controller="myCtrl">
<table>
<thead>
<tr>
<th>请选择</th>
<th>姓名</th>
<th>生日</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="tmp in chose">
<td>
<input type="checkbox" ng-click="funChage()" />
</td>
<td>{{tmp.name}}</td>
<td>{{tmp.br}}</td>
</tr>
</tbody>
</table>
<input type="checkbox" ng-model="selectAll" ng-click="changeAll()" />全选/取消全选
<button ng-click="chakan()">查看</button>
</div>
<script>
var app = angular.module('mymodule',['ng']);
app.controller('myCTRL',['$scope',function($scope){
$scope.chose = [
{name:'king',br:'2019-7-29',isSelected:false},
{name:'Golden',br:'2019-7-30',isSelected:false},
];
$scope.changeAll = function(){ //全选/取消全选
$scope.chose[0].isSelect = $scope.selectAll;
$scope.chose[1].isSelect = $scope.selectAll;
};
$scope.funChange = function(){ //都选就全选
$scope.selectAll = $scope.chose[0].isSelected && $scope.chose[1].isSelected;
};
$scope.chakan = function(){ //弹出框
var result = "";
if($scope.chose[0].isSelected){
result += ($scope.chose[0].name + "选中了")
}
if($scope.chose[1].isSelected){
result += ($scope.chose[1].name + "选中了")
}
alert (result);
}
}])
</script>
案例5 添加/删除
<div ng-controller="myCtrl">
<button ng-click="loadMore()">添加</button>
<table>
<thead>
<tr>
<th>单价</th>
<th>数量</th>
<th>小计</th>
<th>删除</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="tmp in exr track by $index">
<td ng-repeat="stu in tmp">{{stu}}</td>
<td>{{tmp.price*tmp.number}}</td>
<td>
<button ng-click="delect($index)">删除</button>
</td>
</tr>
</tbody>
</table>
</div>
<script>
var app = angular.module('myModule',['ng']);
app.controller('myCtrl',['$scope',function($scope){
$scope.exe = [
{price: 6,number: 3},
{price: 1,number: 3},
{price: 4,number: 3}
];
$scope.loadMore = function(){ //添加
$scope.exe.push({
price: parseInt(Math.random()*10),
number: parseInt(Math.random()*10)
})
};
$scope.delect = function(index){ //删除
$scope.exe.splice(index,1);
};
}])
</script>