**Angular** 笔记
Angular 笔记
Angularjs 中 ui-sref 和 $state.go 如何传递参数
ng-repeat
[
[{},{}],
[{},{}],
[{},{}]
]
<tbody ng-repeat="t in vm.detailData track by $index" style="border:0">
<tr ng-repeat="i in t track by $index">
<td rowspan="{{i.length}}" ng-show="($index) % i.length == 0">{{i.date}}</td>
<td>{{i.platform}}</td>
</tr>
</tbody>
$apply()与 $digest()以及$Watch()
$watch 队列?
每绑定UI,就往watch队列里插入一条$watch, $watch监视model变化
$digest 循环?
包含两个循环,一个循环evalAsync队列,一个循环$watch队列;
dirty-checking(脏检测)?
$digest循环一遍所有$watch,会再循环一次确认无改变;超过10次会抛出异常,防止无限循环;
$apply ?
事件绑定:ng-click=fn() 相当于$scope.$apply(function(){fn)}) // fn() 被自动传递给$apply()包裹一层;$apply() 默认调用 $rootScope.$digest()
双向绑定:ng-model="foo"的输入框,然后你敲一个f,事件就会这样调用$apply("foo = 'f';")
=>start
- 游览器接受一个angular支持的事件 =>
- 调用$apply =>
- 进入angular 上下文 =>
- 执行$digest循环 =>
- 再$digest(无变化) =>
- 回到游览器上下文,更新dom
<= end
ng-repeat高级
遍历数组:<li ng-repeat="item in array">{{item}}</li>
遍历对象:<li ng-repeat="(key,value) in obj">{{key}} | {{value}}</li>
绑定$$haskKey:
给每个item绑定唯一ID,当数组发生变化时,ID不变!
<li ng-repeat="item in items track by $id(item)"></li>
过滤器:
对item的每个属性进行模糊匹配
<li ng-repeat="item in items |filter: 25"></li>
绑定属性过滤:
对item的某个属性进行模糊匹配
<li ng-repeat="item in items |filter: 25 track by item.age"></li>
保存匹配结果:
把匹配到的结果另存到results数组变量,可供外部使用
<li ng-repeat="item in items |filter: 25 as results"></li>
保存针对某个属性的过滤结果:
<li ng-repeat="item in items |filter: 25 as results track by item.age "></li>
路由传参:
'Root.Offer.EventInfo': {
url: '/EventInfo/:id',
},
'Root.Finance_adv.InvoiceDetail': {
url: '/Invoice/Detail?id&READ',
},
ui-sref="Root.Offer.EventInfo({id:item.id})
ng-model
ngModelController中两个管道数组 $formatters 和 $parsers
$formatters :将Model数据转换为view视图显示的值
$parsers: 将交互控件的view值转换为Model格式的数据
ngModelCtrl.$parsers.push(function(value) {…});
ngModelCtrl.$formatters.push(function(value) {...});
ng-class
ng-class="{true: 'active', false: 'inactive'}[isActive]" //isActive表达式为true,则 active,否则inactive
ng-class = “{‘selected': isSelected, 'car': isCar}" //当 isSelected = true 则增加selected class,
当isCar=true,则增加car class,
ng 原理分析:
脏检测机制的低效
只要变过数据,至少要跑两次脏检测
模块机制
$scope 对象
是一个js 的 POJO
有两个特别的函数:$watch 、$digest
DI 实现原理
在使用模块时无需require()引入,直接通过形参注入到函数所在作用域
js实现DI
angular DI:
ng笔记:
七、模版:
#模版内容:
三种方式:字符串;外部文件,script定义内部文件
ng-include src=“ ‘’ ”
ng-include=“ ‘’ ”
<script type="text/ng-template" id="tpl">here, {{ 1 + 1 }}</script>
<div ng-include src="'tpl'"></div>
渲染控制
节点控制
ng-style
ng-class
ng-show | ng-hide | ng-switch
ng-src
ng-href
数据绑定:
- ng-src src属性
- ng-href href属性
- ng-checked 选中状态
- ng-selected 被选择状态
- ng-disabled 禁用状态
- ng-multiple 多选状态
- ng-readonly 只读状态
事件绑定 (事件对象 $event $event.target)
- ng-change
- ng-click
- ng-dblclick
- ng-mousedown
- ng-mouseenter
- ng-mouseleave
- ng-mousemove
- ng-mouseover
- ng-mouseup
- ng-submit
表单控件
from 动态类:
- ng-valid 当表单验证通过时的设置
- ng-invalid 当表单验证失败时的设置
- ng-pristine 表单的未被动之前拥有
- ng-dirty 表单被动过之后拥有
form 对象的属性有:
- $pristine 表单是否未被动过
- $dirty 表单是否被动过
- $valid 表单是否验证通过
- $invalid 表单是否验证失败
- $error 表单的验证错误
input 相关可用属性为:
- name 名字
- ng-model 绑定的数据
- required 是否必填
- ng-required 是否必填
- ng-minlength 最小长度
- ng-maxlength 最大长度
- ng-pattern 匹配模式
- ng-change 值变化时的回调
- input type="number" 多了 number 错误类型,多了 max , min 属性。
- input type="url" 多了 url 错误类型。
- input type="email" 多了 email 错误类型。
- checkbox 选中ng-true-value="AA" 不选中ng-false-value="BB"
- radio value=“aa”
- select ng-options [数组、对象]
八、过滤器
内置过滤器
1. currency (货币处理) 人民币:{{num | currency : ‘¥’}};默认是美元
2. date (日期格式化) {{date | date : 'yyyy-MM-dd hh:mm:ss EEEE'}}
y M d h m s E 表示 年 月 日 时 分 秒 星期,描述性字符串:“shortTime”将会把时间格式为12:05 pm
3. filter(匹配子串)
$scope.childrenArray = [{name:'shitou',age:6},{name:'tiantian',age:5}];
$scope.func = function(e){return e.age>4;}
{{ childrenArray | filter : 'a' }} //匹配属性值中含有a的
{{ childrenArray | filter : {name : 'i'} }} //参数是对象,匹配name属性中含有i的
{{childrenArray | filter : func }} //参数是函数,指定返回age>4的
4. json(格式化json对象) 格式化为json字符串,和JSON.stringify()一样
5. limitTo(限制数组长度或字符串长度) {{ childrenArray | limitTo : 2 }} //将会显示数组中的前两项
6. lowercase(小写)
7. uppercase(大写)
8. number(格式化数字) //默认加上千位123,456,789。接收参数指定保留小数位 {{ num | number : 2 }}
9. orderBy(排序)
参数为字符串,表示以该属性名称进行排序。
参数为函数,定义排序属性。
参数为数组,表示依次按数组中的属性值进行排序(若按第一项比较的值相等,再按第二项比较)
<div>{{ childrenArray | orderBy : 'age' }}</div> //按age属性值进行排序,若是-age,则倒序
<div>{{ childrenArray | orderBy : orderFunc }}</div> //按照函数的返回值进行排序
<div>{{ childrenArray | orderBy : ['age','name'] }}</div> //如果age相同,按照name进行排序
自定义过滤器
使用module的filter方法,返回一个函数,该函数接收输入值,并返回处理后的结果。
比如我需要一个过滤器,它可以返回一个数组中下标为奇数的元素,代码如下:
app.filter('odditems',function(){
return function(inputArray){
var array = [];
for(var i=0;i<inputArray.length;i++){
if(i%2!==0){
array.push(inputArray[i]);
}
}
return array;
}
});
处理逻辑就写在内部的闭包函数中。你也可以让自己的过滤器接收参数,参数就定义在return的那个函数中,作为第二个参数,或者更多个参数也可以。
九、路由
十、定义模版变量标识符
十一、Ajax
$http
$q
十二、工具函数
angular.bind()
angular.copy()
angular.extend()
空函数: angular.noop()
大小写转换: angular.lowercase()和 angular.uppercase()
JSON转换: angular.fromJson()和 angular.toJson()
遍历: angular.forEach(),支持列表和对象
类型判定
- angular.isArray
- angular.isDate
- angular.isDefined
- angular.isElement
- angular.isFunction
- angular.isNumber
- angular.isObject
- angular.isString
- angular.isUndefined
十三、其它服务
日志 $log
缓存 $cacheFactory
计数器 $timeout $timeout.cancel()取消
表达式函数化 $parse
模版单独使用 $compile
十四、自定义模块与服务
ng模块(默认模块):提供$http,$q等服务
模块提供包括:服务、指令、过滤器、及其他配置信息等机制
使用时,模块需要显示声明依赖,服务可以通过ng自动注入
自定义服务:
provider对象 :被“注入控制器”使用的一个对象 注入机制通过provider.$get(),把得到的东西作为参数进行相关调用
eg:把得到的服务作为一个controller 的参数
底层方法:
$provider.provider(‘pp’, function(){this.$get = ()=>{‘haha’:’1234’}})
//定义一个叫pp的服务,pp服务也就是pp这个provider的get()返回的东西
factory 返回object
$provider.factory(‘pp’, function(){return {}})
app.factory('PP', function(){return {'abc': '123'}});
service 可以是数字、字符串
app.service('PP', function(){this.abc = '123';});
provider
1. 为应用提供通用的服务,形式可以是常量或对象
2. 便于模块化
3. 便于单元测试
provider可写成
$provide.provider('age', {
start: 10,
$get: function() {
return this.start + 2;
}
});
//或
$provide.provider('age', function($filterProvider){
this.start = 10;
this.$get = function() {
return this.start + 2;
};
});
//调用:
app.controller('MainCtrl', function($scope, age) {
$scope.age = age; //12
});
其原理是通过实现$get方法来在应用中注入单例,使用的时候拿到的age就是$get执行后的结果
factory可以写成
$provide.factory('myDate', function(){
return new Date();
});
service可写成
$provide.service('myDate', Date);
value & constant
区别一:****value****可以被修改,****constant****一旦声明无法被修改
1 $provide.decorator('pageCount', function($delegate) {
2 return $delegate + 1;
3 });
decorator可以用来修改(修饰)已定义的provider们,除了constant~
区别二:****value****不可在****config配置函数里注入,****constant****可以
1 myApp.config(function(pageCount){
2 //可以得到constant定义的'pageCount'
3 });
十五、附加模块 ngResource
十六、与其它框架混用
ng 最忌讳修改 DOM 结构——应该使用 ng 的模板机制进行数据绑定,以此来控制 DOM 结构,而不是直接操作。
数据使用哪个框架来控制都是没问题的,如有必要使用 $scope.$digest() 来通知 ng 一下即可
十七、自定义过滤器
filter 就是一个函数,虽然定义在module下,但无任何上下文关联的能力
app.filter('map', function(){
var filter = function(input){return input + '...'; };
return filter;
});
使用:{{ a|map}}
传参:{{ a|map:map_value:'>>':'(no)' }}
十八、自定义指令
指令返回一个对象 return{};返回return fn的话,fn将作为link函数使用
directive的执行过程:
-
浏览器解析html字符串得到 DOM 结构
-
ng 引入,把 DOM 结构扔给 $compile 函数处理:
-
找出 DOM 结构中有变量占位符
-
匹配找出 DOM 中包含的所有指令引用
-
把指令关联到 DOM
-
关联到 DOM 的多个指令按权重排列
-
执行指令中的 compile 函数(改变 DOM 结构,返回 link 函数)
-
得到的所有 link 函数组成一个列表作为 $compile 函数的返回
-
执行 link 函数(连接模板的 scope)。
-
浏览器把 HTML 字符串解析成 DOM 结构。
-
ng 把 DOM 结构给 $compile ,返回一个 link 函数。
-
传入具体的 scope 调用这个 link 函数。
-
得到处理后的 DOM ,这个 DOM 处理了指令,连接了数据。
一个完整指令返回一个对象,包含compile、link、restrict等属性;
如果指令返回一个函数fn,则这个fn会作为compile的返回值,也即作为link函数使用;
指令包含的属性
- name
- priority
- terminal
- scope
- controller
- require
- restrict
- template
- templateUrl
- replace
- transclude
- compile
- link
app.directive('color', function(){
var link = function($scope, $element, $attrs){
$scope.$watch($attrs.color, function(new_v){
$element.css('color', new_v);
});
}
return link;
});
compile的细节
基本形式
let link = $compile(‘<div></div>’); //返回link函数
let node = link($scope, cloneAttachFN);// cloneAttchFn表示是否复制原始节点以及对复制节点需要做的处理
注意:这里不能做数据绑定;因为{{ }}在 $compile 中已被处理过,生成了相关函数;后面执行 link 就是执行了 $compile 生成的这些函数。如果你的文本没有数据变量的引用,那修改是会有效果的。
link 函数是由 compile 函数返回的;应该把改变 DOM 结构的逻辑放在 compile 函数中做。
$compile另外两个参数:
$compile(element, transclude, maxPriority);
$compile
解析html模板
返回两个函数pre-link和post-link
先执行pre-link,从父节点到子节点遍历,在这个阶段,进行一些初始化数据的处理。
第二执行的是post-link,即link函数,从子节点到父节点遍历,在这个阶段,DOM节点已经稳定下来
$parse 服务
解析表达式,将一个表达式转换为一个函数
var getter = $parse('user.name');
var setter = getter.assign;
setter(scope, 'new name');
getter(context, locals) // 传入作用域,返回值 context含有你要解析语句中的表达式,通常为一个scope对象
setter(scope,'new name') // 修改映射在scope上的属性的值为‘new value’
$eval()方法
基于$parse, 作为scope的方法使用;scope.$eval('a+b'); 而这个里的a,b是来自 scope = {a: 2, b:3};
transclude
transclude:true //在指令中说明需要嵌入
ng-transclude //在模版中说明要嵌入的位置
取出自定义指令中的内容(就是写在指令里面的子元素),以正确的作用域解析它,然后再放回指令模板中标记的位置(通常是ng-transclude标记的地方),
注入服务
服务可以定义在任意模块,注入服务时需要引入所在的模块依赖;
link
link函数的$attrs 参数 : 指令元素的属性合集;
$attrs.$observe()方法: 监听属性变化,触发一个回调函数
$scope 的属性
$id: "002" scope唯一标示
$root: Scope 根scope
$parent: null 父scope
$$childHead: null 第一个子scope
$$childTail: null 最后一个子scope
$$prevSibling: null 上一个兄弟scope
$$nextSibling: null 下一个兄弟scope
$$phase: null
$$destroyed: false
$$isolateBindings: Object
$$listenerCount: Object
$$postDigestQueue: Array[0]
$$watchers: Array[1]
$$asyncQueue: Array[0]
////发布订阅事件模型 可在各级controller内传递event和data
$$listeners: Object 在scope上注册事件监听器
//原型继承.proto
$on(evt,fn(args)) 监听处理(名为evt,监听器为fn)
$emit(evt,args) 发送evt事件,冒泡;在当前scope及所有$parents上触发
$broadcast(eat,args) 发送事件eat,捕获;在当前scope及其所有children上触发
"$new",
"$watch",
"$watchCollection",
"$digest",
"$destroy",
"$eval",
"$evalAsync",
"$$postDigest",
"$apply",
constructor
指令的几种参数
内部参数 //描述指令或DOM本身特性的内部参数
restrict:String, E(元素) A(属性,默认值)C(类名) M(注释)
priority: Number, 指令执行优先级
template: String, 指令链接DOM模板,例如“<h1>{{head}}</h1>”
templateUrl:String, DOM模板路径
replace: Boolean, 指令链接模板是否替换原有元素
对外参数scope // scope是指令与外界作用域通讯的桥梁
scope:Boolean or Object 隔离指令与所在控制器间的作用域、隔离指令与指令间的作用域
false 共享父域(默认值);
true 继承父域且新建独立作用;
指令未申明scope.data时, 在指令中可监听父域data。父域变更,指令数据也会变更;但一旦指令中input变更了,指令独立scope也会自动绑定
指令已声明scope.data时,在指令中监听父域data无效。但可通过scope.$parent监听父域
{} 不继承父域且新建独立作用域()
对外参数require // require是指令与指令之间通讯的桥梁
require: String or Array 通过require参数,指令可以获得外部其他指令的控制器,从而达到交换数据、事件分发的目的
require: '^teacher1', 如果require为String,ctrl为对象,如果require是数组,ctrl为数组。
link: function ($scope, $element, $attrs, ctrl) { //ctrl参数指向teacher1指令的控制器}
?策略 寻找指令名称。如果找不到,link第4个参数为null。 假如无“?”则报错。
^ 策略 在自身指令寻找指令名称,同时向上父元素寻找。 假如没有“^”则仅在自身寻找。
行为参数link与controller //描述指令本身行为的行为参数 先controller,后link
controller: 控制器函数;定义指令内部作用域的行为
link 链接函数; 定义指令元素的操作行为
- 分析指令,加载模板,形成DOM模板树
- 执行link,设置DOM各个行为;从最底部指令开始依次执行指令的link函数(适合dom操作,性能开销最小,如鼠标操作或触控事件分发绑定、样式Class设置、增删改元素等等)
- 数据绑定(最后scope绑上DOM)
$watch()
scope对象的方法;推荐在指令的link函数中使用;
可以监测expression和函数的变化,它使用$parse将angular expression解析为一个函数,
这个函数会在angular的每个脏值检查循环中被调用。 $observe()
指令中link函数中实例属性即(iAttr)的方法。 只可以在指令的link函数中使用。 只监测angular expression的变化
异同:
$rootscope之所以被称为"root"的原因就是他是所有scope的祖先,$rootscope是在angular启动流程中建立的(上上期讲过),而被注入到controller中的$scope则是在视图创建的时候通过父辈的$scope.$new制造出来的,在视图销毁的时候,$scope会被跟着销毁。$scope是链接视图和controller的重要手段,controller则是可以与服务进行链接,将服务提供的功能进行组合,然后丢给$scope,$scope则将这些传递给视图,让它显示给用户。如果将一个$scope比作一个人的话,那么他的功能有:生育功能($new)、进食功能($watch)、消化功能($digest)、执行功能($apply)、交流功能($on、$emit、$broadcast)、死亡功能($destory)。
compile & link
只使用了一个link函数,那么ng会把这个函数当成post-link来处理
compile函数: 返回pre-link post-link
执行顺序: 先compile 再pre-link 再post-link
compile与pre-link函数: 顺序执行
post-link函数: 反序执行
module
- _invokeQueue
:
Array[4]
_runBlocks
:
Array[0]
animation
:
()config
:
()constant
:
()controller
:
()directive
:
()factory
:
()filter
:
()name
:
"PonyDeli"
provider
:
()requires
:
Array[0]
run
:
(block)service
:
()value
:
()
$log 服务
debug()error()info()log()warn()