Angular 笔记
Angularjs 中 ui-sref 和 $state.go 如何传递参数
ng-repeat
[
[{},{}],
[{},{}],
[{},{}]
]
$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高级
遍历数组:
遍历对象:
绑定$$haskKey:
给每个item绑定唯一ID,当数组发生变化时,ID不变!
过滤器:
对item的每个属性进行模糊匹配
绑定属性过滤:
对item的某个属性进行模糊匹配
保存匹配结果:
把匹配到的结果另存到results数组变量,可供外部使用
保存针对某个属性的过滤结果:
路由传参:
'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=“ ‘’ ”
渲染控制
节点控制
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(排序)
参数为字符串,表示以该属性名称进行排序。
参数为函数,定义排序属性。
参数为数组,表示依次按数组中的属性值进行排序(若按第一项比较的值相等,再按第二项比较)
自定义过滤器
使用module的filter方法,返回一个函数,该函数接收输入值,并返回处理后的结果。
比如我需要一个过滤器,它可以返回一个数组中下标为奇数的元素,代码如下:
app.filter('odditems',function(){
return function(inputArray){
var array = [];
for(var i=0;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(),支持列表和对象 类型判定 十三、其它服务 日志 $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', { }); //或 $provide.provider('age', function($filterProvider){ }); //调用: app.controller('MainCtrl', function($scope, age) { }); 其原理是通过实现$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函数使用; 指令包含的属性 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(‘
start: 10,
$get: function() {
return this.start + 2;
}
this.start = 10;
this.$get = function() {
return this.start + 2;
};
$scope.age = age; //12
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模板,例如“
{{head}}
”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()和$observe()
$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()