我爱编程

**Angular** 笔记

2018-01-05  本文已影响51人  神刀

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队列;

dirtychecking(脏检测)?

$digest循环一遍所有$watch,会再循环一次确认无改变;超过10次会抛出异常,防止无限循环;

$apply ?

事件绑定:ng-click=fn() 相当于$scope.$apply(function(){fn)}) // fn() 被自动传递给$apply()包裹一层;$apply() 默认调用 $rootScope.$digest()

双向绑定:ng-model="foo"的输入框,然后你敲一个f,事件就会这样调用$apply("foo = 'f';")

=>start

  1. 游览器接受一个angular支持的事件 =>
  2. 调用$apply =>
  3. 进入angular 上下文 =>
  4. 执行$digest循环 =>
  5. 再$digest(无变化) =>
  6. 回到游览器上下文,更新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

数据绑定:

事件绑定 (事件对象 $event $event.target)

表单控件

from 动态类:

form 对象的属性有:

input 相关可用属性为:

八、过滤器

内置过滤器

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(),支持列表和对象

类型判定

十三、其它服务

日志 $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的执行过程:

一个完整指令返回一个对象,包含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(‘<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 链接函数; 定义指令元素的操作行为

  1. 分析指令,加载模板,形成DOM模板树
  2. 执行link,设置DOM各个行为;从最底部指令开始依次执行指令的link函数(适合dom操作,性能开销最小,如鼠标操作或触控事件分发绑定、样式Class设置、增删改元素等等)
  3. 数据绑定(最后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

$log 服务

debug()error()info()log()warn()

上一篇下一篇

猜你喜欢

热点阅读