AngularJs $parse、$eval和$observe、$watch详解


Posted in Javascript onSeptember 21, 2016

$parse和$eval

$parse和$eval这两个函数都可以解析表达式的值.

它们的区别在于$parse是一个服务, 可以注入使用. $eval是scope对象上的一个方法, 我们只能在能访问scope的场景下使用它.

var getter = $parse('user.name');
var setter = getter.assign;
var context = {user: {name: 'John Doe'};
var locals = {user: {name: 'Doe John'};

getter(context); //John Doe
setter(context, 'new name');
getter(context); //new name
getter(context, locals); //Doe John

$parse服务接收一个表达式作为参数并返回一个函数. 这个函数可以被调用, 其中的参数是一个context对象, 通常来说是作用域.
另外, 这个函数有一个assign属性. 它也是一个函数, 可以用来在给定的上下文中改变这个表达式的值. 最后一行代码演示了如何使用locals来覆盖context对象.

$eval用起来要简单很多, 因为它的上下文已经被指定为scope对象.

var scope = $rootscope.$new(true);
scope.a = 1;
scope.b = 2;
scope.$eval('a + b')//3
scope.$eval(function(scope){
 return scope.a + scope.b;
});//3

关于$parse和$eval之间的关系, 我们能从Angular源码中看出来, 可以说$eval是为了让$parse在scope中使用更方便的语法糖.

$eval: function(expr, locals){
 return $parse(expr)(this, locals);
}

$eval还有个同胞兄弟, $evalAsync, 它并不会立刻计算表达式的值, 而是将表达式缓存起来, 等到下一次$digest ( 脏检查 ) 的时候执行. 以获取更好的性能.

$observe和$watch

$observe和$watch都可以监听表达式值的变化. 但有显著的不同.
$observe是angular指令中link函数第三个参数 ( attrs ) 的一个方法. 只能在指令的link函数中使用它. 它是通过$evalAsync函数实现监控的.

$watch是scope对象上的一个方法, watch表达式很灵活, 可以是一个函数, 可以是scope上的属性, 也可以是一个字符串形式的表达式. 监听scope上的属性名或表达式的时候, 会利用$parse服务将表达式转换成一个函数, 这个函数会在$digest中被调用. $watch的第三个参数"objectEquality", 指定比较对象的方式, 如果为true,则用angular.equals, 否则直接比较引用. 默认为false.

//html
<div book="{{book.name}}"></div>
//js
attrs.$observe('book', function(newValue){
 //just have one parameter, can't get old value
});
scope.$watch(attrs.book, function(newValue, oldValue){
 //get undefined
});

当你需要监听一个包含"{{}}"的DOM属性时, 使用$observe, 如果用$watch, 只能得到undefined. 反之, 就用$watch. 如果用$observe, 只能得到一个固定的字符串.

//html
<div book="book.name"></div>
//js
attrs.$observe('book', function(newValue){
 //always get 'book.name'
});
scope.$watch(attrs.book, function(newValue, oldValue){
});

有一个特殊的情况, 当你的指令使用了独立的作用域 ( scope:{} ) , 那些应用了"@"语法的DOM属性, 即使包含"{{ }}", 也可以被$watch.

因为@前缀标识符, 它的实现是通过$observe去监听DOM属性的变化, 这就是为什么@attr的值只能是字符串或是"{{}}", 而不能是scope上的属性, 所以最终$watch看到的表达式是没有"{{ }}"的. 而"="和"&"则是基于$watch实现. 所以=attr, &attr的值不能包含"{{ }}", 但可以直接使用scope上的属性.

$watchGroup和$watchCollection

$watchGroup是用来监听一组表达式. 数组中任意表达式的变化都会触发监听函数.

$scope.teamScore = 0;
$scope.time = 0;
$scope.$watchGroup(['teamScore', 'time'], function(newVal, oldVal) {
 //newVal and oldVal are both array
});

$watchCollection用来监听一个对象(包括数组), 当这个对象的任意属性发生变化时, 触发监听函数. 和$watch一样,第一次参数可以是一个返回一个对象的函数.

$scope.names = ['igor', 'matias', 'misko', 'james'];
$scope.dataCount = 4;

$scope.$watchCollection('names', function (newVal, oldVal) {
 $scope.dataCount = newVal.length;
});

$timeout(function(){
  $scope.names.pop();
},2000);

$observe, $watch, $watchGroup, $watchCollection都返回一个移除监听的函数. 当需要取消监听的时候, 直接调用.

var off = scope.$watch('name', function(newValue, oldValue){
});
off();

以上就是对AngularJs $parse、$eval和$observe、$watch的知识详解,谢谢大家对本站的支持!

Javascript 相关文章推荐
用javascript操作xml
Nov 04 Javascript
用ADODB.Stream转换
Jan 22 Javascript
一个加载js文件的小脚本
Jun 28 Javascript
jQuery语法高亮插件支持各种程序源代码语法着色加亮
Apr 27 Javascript
jQuery实现鼠标可拖动调整表格列宽度
May 26 Javascript
使用jsonp完美解决跨域问题
Nov 27 Javascript
js实现选中复选框文字变色的方法
Aug 14 Javascript
原生js实现class的添加和删除简单代码
Jul 12 Javascript
JS实现的点击表头排序功能示例
Mar 27 Javascript
详解Node.js项目APM监控之New Relic
May 12 Javascript
vue踩坑记录之数组定义和赋值问题
Mar 20 Javascript
JavaScript事件冒泡机制原理实例解析
Jan 14 Javascript
jQuery+CSS3实现仿花瓣网固定顶部位置带悬浮效果的导航菜单
Sep 21 #Javascript
D3.js实现散点图和气泡图的方法详解
Sep 21 #Javascript
AngularJs ng-repeat 嵌套如何获取外层$index
Sep 21 #Javascript
D3.js实现饼状图的方法详解
Sep 21 #Javascript
angularJS Provider、factory、service详解及实例代码
Sep 21 #Javascript
JS实现图文并茂的tab选项卡效果示例【附demo源码下载】
Sep 21 #Javascript
AngularJS ngModel实现指令与输入直接的数据通信
Sep 21 #Javascript
You might like
php制作文本式留言板
2015/03/18 PHP
php使用number_format函数截取小数的方法分析
2016/05/27 PHP
JXTree对象,读取外部xml文件数据,生成树的函数
2007/04/02 Javascript
HTML中事件触发列表与解说
2007/07/09 Javascript
jQuery版仿Path菜单效果
2011/12/15 Javascript
Jquery带搜索框的下拉菜单
2013/05/06 Javascript
解析JavaScript中delete操作符不能删除的对象
2013/12/03 Javascript
JS实现让网页背景图片斜向移动的方法
2015/02/25 Javascript
jquery实现公告翻滚效果
2015/02/27 Javascript
javascript实现在指定元素中垂直水平居中
2015/09/13 Javascript
javascript实现input file上传图片预览效果
2015/12/31 Javascript
使用递归遍历对象获得value值的实现方法
2016/06/14 Javascript
jQuery Easyui加载表格出错时在表格中间显示自定义的提示内容
2016/12/08 Javascript
BootStrap Fileinput上传插件使用实例代码
2017/07/28 Javascript
Angular ng-animate和ng-cookies用法详解
2018/04/18 Javascript
python实现清屏的方法
2015/04/30 Python
Python如何获取系统iops示例代码
2016/09/06 Python
Python实现数据可视化看如何监控你的爬虫状态【推荐】
2018/08/10 Python
selenium3+python3环境搭建教程图解
2018/12/07 Python
用python脚本24小时刷浏览器的访问量方法
2018/12/07 Python
python双端队列原理、实现与使用方法分析
2019/11/27 Python
Python变量、数据类型、数据类型转换相关函数用法实例详解
2020/01/09 Python
Python3标准库之dbm UNIX键-值数据库问题
2020/03/24 Python
python 实现分组求和与分组累加求和代码
2020/05/18 Python
python实现定时发送邮件到指定邮箱
2020/12/23 Python
Smashbox英国官网:美国知名彩妆品牌
2017/11/13 全球购物
斯德哥尔摩通票:Stockholm Pass
2018/01/09 全球购物
关键字throw与throws的用法差异
2016/11/22 面试题
物业管理大学生个人的自我评价
2013/10/10 职场文书
酒店管理毕业生自荐信
2013/10/24 职场文书
副护士长竞聘演讲稿
2014/04/30 职场文书
学习雷锋标语
2014/06/25 职场文书
2015年员工工作总结范文
2015/04/08 职场文书
升职感谢领导的话语及升职感谢信
2019/06/24 职场文书
导游词之河北白洋淀
2020/01/15 职场文书
win10输入法不见了只能打出字母怎么解决?
2022/08/05 数码科技