前端之家收集整理的这篇文章主要介绍了
angular指令心得(ng-model),
前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
angular指令心得(ng-model)
在项目中编写指令,常常会依赖其他的指令来实现想要达到的功能,其中最常用到的便是ng-model,它为我们明确了需要绑定的属性,虽然在指令中可以通过通过使用独立作用域的”=”来进行双向绑定,但使用ng-model更能简化指令的传值,符合angular的使用习惯。
指令依赖
angular中编写自定义指令是通过require属性来指定查找依赖指令的controller,并传入link函数中进行调用.
.directive(
"...",
function(){
return {
...
require:
'ngModel',link:
function(scope,elem,attr,ngModelCtr){
...
}
...
}
})
所依赖指令的控制器被传入link的第四个参数中,可以依赖多个指令,此时第四个参数则是个数组。
require:['^?form',136); Box-sizing: border-Box;">...],ctrls){
在查找指令的过程中,如果未找到指令,则会抛出一个编译错误。
可以通过加前缀来控制其查找的操作。
前缀 |
作用 |
^ |
向上查找指令,未找到则报错。 |
? |
未找到,取消报错,将null传到link的第四个参数。 |
ng-model
使用ng-model前,让我们先简单了解一下ng-model的工作原理。
angular是一个mvvm的框架,其主要就体现在ng-model身上
angular将model和view之间的联系切断,自己内部通过ng-model去实现viewmodel层,具体的细节不表,我们就看下我们要用的部分。
在每个使用ng-model的地方,都会创建一个ngModelController实例,这个实例负责管理存储在模型(由model指定)中的值与元素显示值之间的数据绑定。
ngModelController包含有$formatters和$parsers数组,会在每次更新数据绑定是调用。
当我们从页面或通过$setViewValue改变绑定的属性时,会遍历执行$parsers数组里面的方法,而当我们直接在js里面通过赋值语句修改时,则会调用$formatters数组。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
$scope.$watch(function ngModelWatch() {
var modelValue = ngModelGet($scope);
if (modelValue !== ctrl.$modelValue &&
(ctrl.$modelValue === ctrl.$modelValue || modelValue === modelValue)
) {
ctrl.$modelValue = ctrl.$$rawModelValue = modelValue;
parserValid = undefined;
var formatters = ctrl.$formatters,idx = formatters.length;
var viewValue = modelValue;
while (idx--) {
viewValue = formatters[idx](viewValue);
}
if (ctrl.$viewValue !== viewValue) {
ctrl.$viewValue = ctrl.$$lastCommittedViewValue = viewValue;
ctrl.$render();
ctrl.$$runValidators(modelValue,viewValue,noop);
}
}
return modelValue;
});
}];
上面是angular调用$formatters的地方,它监控了model值的变化,负责model->view。
实践
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
<html lang="en" > head> Meta charset=
"utf-8">
http-equiv=
"X-UA-Compatible" content=
"IE=edge">
title>angular-ngModel-test
</title> script type=
"text/javascript" src=
"http://cdn.bootcss.com/angular.js/1.5.0-beta.1/angular.js">
script>
"text/javascript">
angular.module("testModule",[]) .controller("testCtr",function($scope){ }) .directive("testDire",102); Box-sizing: border-Box;">(){
return { restrict:
"A",
require:
"ngModel",link:
(scope,ngModelCtr){ } } })
body ng-app=
"testModule" ng-controller=
"testCtr">
input "text" test-dire ng-model=
"say"/>
h1>
{{say}} h1> body>
html>
上面搭建了一个基本的架子,现在我们通过来通过js改变模型值,在$formatters里面加入一个格式化方法来显示到页面上。
改动:
1
2
3
4
5
6
7
8
9
10
button ng-click="joke()">窗前明月光
button>
h1 </
body>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
.directive(
(){
return {
restrict:
(modelValue){
if(
typeof modelValue !=
"undefined"){
return "李白睡的香";
}
})
}
}
})
效果图:
这里有个很奇怪的现象,两个绑定model的地方显示的值不一样,这是因为input是从ngModelController中获得的返回值显示出来的,这个值在通过$formatters数组时被我拦截下来,返回了另外一个字符串。
$parsers
我们还可以对界面(view)输入后的值进行处理。
改动:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//js
.directive(
...
ngModelCtr.$parsers.push(
function(viewValue){
if(typeof viewValue !=
"undefined"){
"我说:"+viewValue;
}
})
}
}
})
效果图:
$render &$setViewValue
$render
有的时候,$formatters数组里面也许会有不止一个方法,这时候为了保证一个最终的显示效果,就应该用到$render方法。
TIP:$render总会在$formatters完成之后调用。
重新赋值$render方法,在改变模型值后修改字体颜色。
改动:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
//js
.directive(
...
var h1Elem = document.getElementsByTagName(
"h1")[
0];
ngModelCtr.$render =
function(){
if(typeof scope.say !=
"undefined"){
h1Elem.style.color =
"red";
}
}
}
}
})
结果可以看到,颜色成功改变了,但是输入框没有变化。
造成这个的原因是因为我们重写了$render方法,相当于改写了ng-model从model到view的dom操作,用自己的方式去实现。
$setViewValue
的作用是为了在指令中改变ng-model绑定的值,适用于使用了独立作用域的指令(在没有双向绑定属性的情况下,无法通过scope进行赋值)。
下面在加载自执行的时候通过指令改变模型值。
改动:
1
2
3
4
5
6
7
8
9
10
11
12
13
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
//js
.directive(
...
ngModelCtr.$setViewValue(
"hello");
}
}
})
总结
在指令中,我们可以用通过简单的依赖ng-model去实现angular各种其他插件的兼容(如一些日期控件,富文本编辑器等),更能简化我们的指令代码,避免很多复杂的绑定逻辑,特别要注意的是$formatters,$passers,$render这些都会在初始化时去执行一遍,因此应该根据需要做好判断操
转http://blog.csdn.net/qq_17371033/article/details/49248791