1.介绍
angular 是Google公司提供的一套开源的javascriptMVC框架。核心功能就是对现有的HTML编码以指令方式进行扩展,并且使扩展后的HTML编码
可以通过使用元素声明的方式来构建动态内容。-- 通过HTML标签构建动态的web应用。
2.核心
要实现HTML标签构建动态的Web应用:数据的双向绑定(表达式{{data}})和依赖注入
3.开始
(1).ng-app
表示此节点一下为angular的应用
(2)表达式 {{}}
表达式是运用在视图中的一段代码 ,表达式的值 通过 $parse 服务模块进行解析的。
*angular表达式跟js表达式区别
a.angular表示的值来源于$scope对象 js来自window
b.angular表达式 的容错率很强 看允许出现null 和undefined 不会像js抛出异常代码
c.angular不能出现各类判断和循环语句
d.angular可以出现 "|"管道符进行格式化
*与js相互转换
==>js $eval()
==>angular 采用函数 表达式为函数调用
(3)$window 通过依赖注入
eg: $window.alert('window 对象')
(4)模板
构建 js文件的html
eg: template.js 根据视图的一样
使用 : 引入 <script src='template.js' type='text/ng-template' id='template'></script>
html
<div ng-inculde src='"template"'></div>
(5)ng-repeat
track by $index 是每一项都是唯一 如若不加上 当数据相同的时候只会展示一条
·$index 记录的索引
·$first 记录的第一条
·$last 记录的最后一条
·$middle 记录的中间条
(6)添加样式
(1)class类
a.通过$scope设置变量
$scope.addClass = 'container';
<div ng-class='{{addClass}}'></div>
b.字符串数组方式选择性添加css类别名称
eg: $scope.isTrue = true;
<div ng-class='{true:"test1",false:'test2'}[isTrue]'></div>
c.通过key/value对象方式
eg: $scope.a = true;
$scope.b = false;
<div ng-class='{"test1":a,"test2":b}'></div>
d.通过函数返回字符串
eg:
$scope.getClass = function(){
return 'test3';
}
<div ng-class='getClass'></div>
ng-class-odd ng-class-even
奇偶项
eg:
css
.odd{color:#333} .even{color:#666}
<div ng-class-odd='"odd"' ng-class-even='"even"'></div>
(7)显示/隐藏
ng-show ng-hide ng-switch
显示: ng-show 为true ng-hide 为false
eg: $scope.isShow = true
$scope.ishide = false
<span ng-show='isShow'></span>
<span ng-show='ishide'></span>
ng-switch 要配合 ng-switch-when 和 ng-switch-default
eg:
$scope.switch = 2;
<ul ng-switch on={{switch}}>
<li ng-switch-when='1'></li>
<li ng-switch-when='2'></li>
<li ng-switch-when='3'></li>
<li ng-switch-default>默认</li>
</ul>
(8)表单基本验证功能
$pristine 表示表单或者控件内容是否未输入过 返回布尔
$dirty 表示表单或者控件内容是否已输入过
$valid 表示表单或者控件内容是否已验证通过
$invalid 表示表单或者控件内容是否未验证通过
$error 表示表单或者控件验证时的错误信息
eg:
<form name='myForm' ng-submit='save()'>
<div>
<input name='myInp' ng-model='email' type='email' requied/>
<span ng-show='myForm.myInp.$error.required'>邮件不能为空</span>
<span ng-show='myForm.myInp.$error.email'>邮件格式不正确</span>
</div>
<div>
<input type='submit' ng-disabled='myForm.$invalid' value='提交'/>
</div>
(9).select
a.简单数组
$scope.arr = ['A','b','C'];
// ..for...in..
<select ng-model='seleData' ng-options='item for item in arr'>
<option value=''>-- 请选择 --<option>
</select>
b.数组对象
$scope.arrData = [
{id:1,name:'张三',age:20},
{id:2,name:'李四',age:30},
{id:3,name:'王五',age:40}
]
// ... as...for ...in..
<select ng-model='seleData' ng-options='item.id as item.name for item in arrData'>
<option value=''>-- 请选择 --</option>
</select>
c.分组形式
$scope.arrData = [
{id:1,name:'张三',address:'北京'},
{id:2,name:'李四',address:'北京'},
{id:3,name:'王五',address:'上海'},
{id:3,name:'刘二',address:'上海'}
]
// ... as ... group ... by ... for ... in..
<select ng-model='seleData' ng-options='item.id as item.name group by item.address for item in arrData'>
<option value=''>-- 请选择 --</option>
</select>
(10)依赖注入
前言: new object 新创建的对象 依赖于new 后面的原对象 ,这种方式称为创建性依赖。
而 angualr采用的是注入依赖 angualr通过injector注入器将所依赖的对象进行“注入”操作
eg:
var app = angular.module('myApp',[]);
app.config(function($controllerProvide){
$controllerProvide.register('myCtr',['$scope',function($scope){
// code by controller
}])
})
上面对控制器的创建 等价于
app.controller('myCtr',['$scope',function($scope){
// code ny controller
}])
原理: 通过模块中的config函数来声明需要注入的依赖对象,而声明的方式是通过调用controllerProvide服务的register方法完成创建
当控制器完成后,则再调用inject注入器完成各依赖对象的注入
config除了controllerProvide 还有 provide服务
通过provide的provide、factory、service、value方法创建自定义的依赖注入对象
eg:
var app = angular.module('myApp',[]);
app.config(function($provide){
$provide.provide('proTest',function(){
this.$get = function(){
return {
val: function(data){
return data;
}
}
}
});
});
app.config(function($provide){
$provide.factory('facTest',function(){
return {
val: function(data){
return data;
}
}
});
});
app.config(function($provide){
$provide.service('serTest',function(){
return {
val: function(data){
return data;
}
}
});
});
app.config(function($provide){
$provide.value('valTest',function(data){
return data;
});
});
使用:
app.controller('myCtr',['$scope','proTest','facTest','serTest','valTest',function($scope,
proTest,facTest,serTest,valTest){
$scope.pro = proTest.val('111');
$scope.fac = facTest.val('111');
$scope.ser = serTest.val('111');
$scope.val = valTest('111');
}]);
除了在控制器中经常使用依赖注入外 使用工厂方法构建服务时 同样也经常需要注入其他的服务。
所谓的工厂方法指的是类似于“config” “factory” “directive” “filter” 等构造性的方法
eg:
angular.module('myApp',[])
.factory('facTest',['dep1','dep2',...,function(dep1,dep2,...){
// code
}])
依赖注入的方式
推断式注入 标记式注入 行内式注入
$injector 常用API
has (是否含有依赖) get(得到依赖实例) invoke()执行一个自定义的函数
(11)服务.
内置服务 常用的服务 $scope $http $window $location等
直接在控制器中调用
自定义服务
一种是使用内置 $provide的内置服务
eg:
angular.module('myApp',[],function($provide){
$provide.factory('mySer',function(){
return {
val: function(data){
return data;
}
}
})
}).controller('myCtr',['$scope','mySer',function($scop,mySer){
$scope.data = mySer.val('hello world!');
}]);
另一种是调用模块(modul)中的服务注册方法 factory service consent value等
factory:
app.factory(name,fn) // app 为构建的模块变量 name 为创建服务的名称 fn为服务的功能函数 可返回一个能被注入对象的数组或函数
eg:
angular.module('myApp',[])
.factory('myFac',function(){
return {
val: function(data){
return data;
}
}
})
service:
app.service(name,fn) // app 为构建的模块变量 name 为创建服务的名称 fn为构造函数 当被注入的时候可以通过new实例化对象
eg:
angular.module('myApp',[])
.service('mySer',function(){
this.fn = function(path){
return path;
}
}).controller('myCtr',function($scope,mySer){
$scope.path = mySer.fn('www.baidu.com');
});
consent 和value
app.consent(name,value) 返回一个常量
app.value(name,value) 返回一个常量
eg:
angular.module('myApp',[])
.consent('myCon',{
name:'张三',
address:'北京'
})
.controller('myCtr',function($scope,myCon){
$scope.userName = myCon.name;
$scope.userAddr = myCon.address;
});
angular.module('myApp',[])
.value('color','#E4393C').controller('myCtr',function($scope,color){
$scope.color = color;
});
添加自定义服务的依赖方法
1.隐式指明
app.factory('myFac',function(dep1,dep2){...})
2.调用$inject
var fn = function(dep1,dep2){...}
fn.$inject = ['dep1','dep2']
app.factory('myFac',fn)
3.显示声明
app.factory('mySer',['dep1','dep2',function(dep1,dep2){...}])
服务器的装饰器 decorator
$provide.decorator('serviceName',fn)
eg:
angular.module('myApp',[])
.factory('myFac',function(){
return {
name: '张三',
address:'北京'
}
}).config(function($provide){
$provide.decorator('myFac',function($delegate){
$delegate.name = '李四';
return $delegate;
})
}).controller('myCtr',function($scope,myFac){
$scope.user = myfac;
console.log($scope.user.name); // 李四
});
(12)与服务端交互
1.使用$http快捷方法
$http.method(url,[data],[config])
.success(data,status,headers,config)
.error(data,status,header,config)
eg:
angular.module('myApp',[])
.config(function($httpProvide){
$httpProvide.defaults.headers.post = {
'content-Type':'application/x-www-form-urlencoded'
}
}).controller('myCtr',function($scope,$http){
var params = {name:'张三',address:'北京'};
var url = 'wewewe.com/sdsds/dsd';
$http.post(url,params)
.success(function(data){
console.log(data);
})
.error(function(error){
console.log(error)
})
})
2.使用$http配置对象方式与服务端交互
$http({
method:'POST',
url:'....',
data:data,
params:
transformRequest:
transformResponse:
cache:
timeout:
}).success(fn1).error(fn2)
等价于
$http({
//配置对象
}).then(fn1,fn2)
(13)缓存
angular 提供 $cacheFactory 服务缓存
格式:
$cacheFactory(key,[options]) // key 表示缓存对象的名称 options是一个对象用于指定缓存的特征
$cacheFactory.get(key) // 创建或获取缓存对象
1.info 方法
var cache = $cacheFactory("test");
console.log(cache.info()) // 缓存对象的大小和名称信息
2.put 方法
put方法可以向缓存对象中以key/value的形式添加缓存内容
cache.put('test','hello')
3.get 方法
get方法可以获取键名对应的键值
cache.get('test')
4.remove 方法
remove方法用于移除指定键名的缓存
cache.remove('test')
5.removeAll 和 destory方法
removeAll 移除全部的缓存内容 并且重置缓存结构
destory 是从 $cacheFactory 缓存注册表中删除所有的缓存引用条目,并且重置缓存对象
eg:
angular.module('myApp',[])
.service('cache',function($cacheFactory){
return $cacheFactory('test')
})
(14)promise 对象
angular 中创建一个promise对象 必须在模板中先注入$q服务,并先调用defer方法创建一个延期对象
eg:
angular.module('myApp',function($scope,$q){
var defer = $q.defer();
})
defer 是一个延期对象 包括3个方法 分别是 notify resolve reject 和"promise"属性
当调用延期对象的"promise"的属性时 就创建一个promise对象
eg:
var promise = defer.promise
promise.then(successCallback,errorCallback,notifyCallback)
promise 在$http中的应用
angular.module('myApp',[])
.factory('myFac',function($q,$http){
var defer = $q.defer()
$http.get(url)
.success(function(data){
defer.resovle(data);
})
.error(function(reson){
defer.reject(reson)
})
return defer.promise
}).controller('myCtr',function($scope,myFac){
myFac.then(function(data){
console.log(data)
})
})
(15)指令
一种执行的信号 eg html中a标签 告诉浏览器的编译系统,要创建一个超链接 angular指令是一个在特定DOM元素上执行的函数
指令是angular的一个特殊标志 也是有别于其他框架的一个重要特征 angular之所以功能强大,在很大
的程度上得益于它拥有大量内置的指令 也能通过语法自定义指令。可以说指令是开发angular应用时一个
非常重要的道具,尤其是自定义的指令
自定义指令:调用directive方法
语法:
app.directive(name,fn)
eg:
app.directive('myDire',function(){
return {
restrict: 'EA',
template: '<h1>hello world</h1>',
replace:true
}
})
<my-dire></my-dire> 或者 <div my-dire></div>
说明:
restrict 指出在HTML中的使用方式 包括: E (元素) A(属性) C(类) M(注释) 可以是一种或者组合
template 模板 templateUrl 模板文件
replace 是否替换指令标记
几个重要的属性
transclude <Boolean> 一旦开启属性 可以将调用指令后的元素替换为指令中的模板内容,如果模板中的内容没有元素标签,
而是纯文本内容,那么在替换时会自动添加一个<sapn>标签 不仅仅是内容的替换
eg:
angular.module('myApp',[])
.directive('myDir',function(){
return {
restrict:'EA',
template: '<div>'+
'<input type="text" ng-model="text" />'+
'<div ng-translude></div>'+
'</div>',
transclude: true
}
})
<my-dir>{{text}}</my-dir>
link 属性
link属性值是一个函数 在该函数中科院操控DOM元素对象 包括绑定的各类事件 定义事件触发执行的内容
link: function(scope,iEle,iAttrs){
// code
}
scope: 表示指令所在的作用域 其功能跟控制器中注入的作用域是相同的
iELe: 指令中的元素 该元素可以通过angular内部封装的jqLite框架进行调用 jqLite框架与jquery框架
在功能上差别很大 但是它包含了主要元素操作的api 是一个压缩版的jquery 在语法上与jquery相同
iAttrs: 指令元素的属性集合 通过这个参数可以获取元素中的各类属性
eg:
angular.module('app',[])
.directive('myDir',function(){
return {
restrict:'EA',
template: '<div><button>点击</button><span>{{text}}</span></div>',
transclude: true,
link: function (scope,iEle,iAttrs) {
iEle.bind('click',function(){
scope.$apply(function () {
scope.text = '点击以后'
})
})
}
}
})
<div ng-app="app">
<my-dir></my-dir>
<div>{{text}}</div>
</div>
complete 属性
返回一个函数或者一个对象 一个函数 函数名为post 返回对象 包含两个 pre post名的方法函数 系统提供不可更改
注: 当添加complete时 不能再添加link属性
eg:
app.directive('dir',function(){
return {
restrict:'EA',
compile: function(tEle,tAttrs,trans){
return {
pre: function(scope,iEle,iAttrs){
// code
},
post: function(scope,iEle,iAttrs){
// code
}
}
}
}
})
scope 属性
属性值 Boolean 为true 创建新的作用域 父、子作用域数据完全不相同
false 不创建新的作用域 父、子作用域数据完全相同
属性值为JSON时
JSON对象添加的3中策略 "@attrName" "=attrName" "&attrName"
'=' 父变子也变 字变父也变 一般为值 值用{{}}
'@' 父变字变 字变父不变 一般为值 值用 ''
'&' 一般为函数 用 '()'
eg:
<div ng-app="app" ng-controller="myCtr">
<div>
<input type="text" ng-model="username" placeholder="名字">
</div>
<div>
<input type="text" ng-model="userphone" placeholder="电话号码">
</div>
<my-dir uname="username" uphone="{{userphone}}" uage="userage()"></my-dir>
</div>
<script>
angular.module('app',[])
.controller('myCtr',function($scope){
$scope.userage = function(){
$scope.username = '张三';
$scope.userphone = '1111111111111';
}
})
.directive('myDir',function(){
return {
scope:{
usname:'=uname',
usphone:'@uphone',
usage:'&uage'
},
restrict:'EA',
template: '<div>' +
'<input type="text" ng-model="usname" placeholder="姓名">' +
'<input type="text" ng-model="usphone" placeholder="电话号码">' +
'<button>修改</button>' +
'</div>',
transclude: true,
link: function (scope,iEle,iAttrs) {
scope.usname = '李四';
scope.usphone = '22222';
iEle.bind('click',function(){
scope.$apply(function () {
scope.usage();
})
})
}
}
})
</script>
require 和 controller属性 用于多级指令 或者指令嵌套
(16) $location
提供只读和读写api
只读
absUrl: URL地址中编码后的完整内容
protocol: 协议
host: 主机名称
port: 端口号
eg:
angular.module('myApp',[])
.controller('myCtr',['$scope','$location',function($scope,$location){
$scope.absUrl = $location.absUrl();
$scope.protocol = $location.protocol();
$scope.host = $location.host();
$scope.port = $location.port();
}])
读写方法:加参数表示重置 不加参数表示获取 返回$location对象 所以支持链式调用
url: 修改/获取"#"后面的内容
hash: 修改/修改hash
search:修改/查询 查询字符串内容
path: 修改/查询当前路径
事件:
$locationChangeStart url地址发生改变之前
eg:
angular.module('myApp',[])
.controller('myCtr',function($scope,$rootScope,$location){
$rootScope.$on('$locationChangeStart',function(evt,current,previous){
})
})
其中
evt: 表示触发是时的原始事件对象
current: 当前的url地址
previous: 表示上一级的url地址 如果首次加载 为undefined
$locationChangeSuccess URl地址完成改变后触发
参数与$locationChangeStart 一直
路由模式和地址变更
路由模式分为标签(hashbang)和HTML5两种模式
hashbang :angular默认的路由模式 是HTML5模式的降级方案 url会 "#"符号开头 后面紧跟着
一个"!"符号
重置:
$locationProvide.html5Mode('boolean || obj')
true : 表示支持html5模式 反之支持标签模式
obj : {enabled:true} 支持html5模式 {enabled:false} 支持标签模式
区别:
标签模式 html5模式
是否默认 是
显示格式 所有浏览器显示标签url格式 支持HTML5history API 显示 其他为标签格式
连接标签是否重写 否 是
是否需要服务端支持 否 是
(17)angular 开发的注意事项和最佳实践
1.建议不再调用jQuery框架 避免两者之间在调用时发生冲突 angualr内含jQlite (jquery的一个子集)
操作DOM可以使用自定义指令
2.dom操作
angular.element(element)
形参element是字符型 (字符串或者DOM元素) 功能是调用 angular内部的jQLite库 返回jQuery对象
eg:
<div ng-app="app" ng-controller="myCtr">
<div><button ng-click="add()">添加</button></div>
<div><button ng-click="del()">删除</button></div>
<ul id="doms">
<li>第一</li>
<li>第二</li>
<li>第三</li>
</ul>
</div>
<script>
angular.module('app',[])
.controller('myCtr',function($scope,$compile){
var htmlTem = '<li>第四</li>';
var template = angular.element(htmlTem);
var newTemplte = $compile(template)($scope);
$scope.add = function(){
angular.element(document.getElementById('doms')).append(newTemplte);
};
$scope.del = function(){
if(newTemplte){
newTemplte.remove()
}
};
})
</script>
$compile 服务时把dom转为Jquery对象 进行编译 一遍调用append方法
3.setTimeout改变属性无效
在angular中调用其他方法 并不会执行 自动执行 $apple 只有绑定在$scope上才会 或者 内置的服务
基于以上两种解决办法
1.
setTimeout(function(){
$scope.$apply(function(){
// code
})
},1000)
2.
$timeout(function(){
// code
},1000)
4.解决双大括号 {{}}绑定元素时闪烁问题
原因: dom加载完成 而数据为渲染完
解决:
可以向元素添加 ng-cloak 属性实现掩藏的效果 纯文本 可以使用 ng-bind='data' 避免使用 {{}}
eg:
<p ng-cloak>{{message}}</p>
ng-cloak 实质会在页面 head添加css样式 让dom 的display 为none 当数据渲染成功以后移除样式
<p ng-bind='message'></p>
5.ng-repeat 问题
a.如果使用了过滤器不能通过$index 定位到对象
b.ng-repeat 的更新数据是重建dom而不是更新
使用 track by .. 排序解决
c.与scope关系
ng-repeat 新建dom会为每个新建的dom元素创建独立的作用域 但是父级的scope是相同的 通过调用
angular.element(domELement).scope() 可以获取某个DOM元素所在的作用域
6.单击事件冒泡
阻止冒泡
<button ng-click='fn($event)'></button>
app.controller('myCtr',function($scope){
$scope.fn = function(event){
event.stopPropagation();
}
})
7.释放多余的 $watch监听 函数
$scope.$watch() 返回$watch 绑定的unbind函数 再次调用 就可以释放它的监听功能
eg:
var watchFun = $scope.$watch('value',function(newValue,oldValue){
// code
});
warchFun(); // 停止监听
8.ng-if 中ng-model值无效 的问题
ng-if指令的功能 与ng-show指令相似 可以控制元素的显示和隐藏
区别: ng-if 指令会移除DOM原有的元素 而 ng-show 指令 只是将元素的 "display" 属性设置"none"
ng-if 会生成一个子作用域 从而与 ng-model无效绑定
解决:
1. 替换 ng-show
2.添加标识 $parent
eg:
<div>{{msg}}</div>
<div ng-if='isShow'>
<input type='text' ng-model='$parent.msg'/>
</div>