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 相关文章推荐
原来Jquery.load的方法可以一直load下去
Mar 28 Javascript
同步文本框内容JS代码实现
Aug 04 Javascript
jQuery图片轮播功能实例代码
Jan 29 Javascript
JavaScript对JSON数据进行排序和搜索
Jul 24 Javascript
JavaScript编写的网页小游戏,很给力
Aug 18 Javascript
Three.js如何实现雾化效果示例代码
Sep 27 Javascript
Vue 2.0入门基础知识之内部指令详解
Oct 15 Javascript
js 原生判断内容区域是否滚动到底部的实例代码
Nov 15 Javascript
css配合JavaScript实现tab标签切换效果
Oct 11 Javascript
Vue 实现从小到大的横向滑动效果详解
Oct 16 Javascript
JavaScript实现拖拽盒子效果
Feb 06 Javascript
Vant+postcss-pxtorem 实现浏览器适配功能
Feb 05 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/06/22 PHP
Linux环境下php实现给网站截图的方法
2016/05/03 PHP
PHP进程通信基础之信号量与共享内存通信
2017/02/19 PHP
PHP利用Mysql锁解决高并发的方法
2018/09/04 PHP
php实现数字补零的方法总结
2018/09/12 PHP
得到文本框选中的文字,动态插入文字的js代码
2007/03/07 Javascript
解决使用attachEvent函数时,this指向被绑定的元素的问题的方法
2007/08/13 Javascript
Dojo 学习笔记入门篇 First Dojo Example
2009/11/15 Javascript
jquery $.each 和for怎么跳出循环终止本次循环
2013/09/27 Javascript
jQuery中find()方法用法实例
2015/01/07 Javascript
jQuery移动页面开发中的触摸事件与虚拟鼠标事件简介
2015/12/03 Javascript
jQuery实现点击后高亮背景固定显示的菜单效果【附demo源码下载】
2016/09/21 Javascript
简易的JS计算器实现代码
2016/10/18 Javascript
JavaScript之创意时钟项目(实例讲解)
2017/10/23 Javascript
JavaScript去掉数组重复项的方法分析【测试可用】
2018/07/19 Javascript
详解Node.js异步处理的各种写法
2019/06/09 Javascript
[05:08]顺网杯ISS-DOTA2赛歌 少女偶像Lunar青春演绎
2013/12/05 DOTA
[01:10]为家乡而战!完美世界城市挑战赛全国总决赛花絮
2019/07/25 DOTA
Python实例分享:快速查找出被挂马的文件
2014/06/08 Python
python单例模式实例分析
2015/04/08 Python
Python常用字符串替换函数strip、replace及sub用法示例
2018/05/21 Python
python中plot实现即时数据动态显示方法
2018/06/22 Python
python3调用百度翻译API实现实时翻译
2018/08/16 Python
python字典值排序并取出前n个key值的方法
2018/10/17 Python
wxpython绘制圆角窗体
2019/11/18 Python
torch 中各种图像格式转换的实现方法
2019/12/26 Python
python中字典增加和删除使用方法
2020/09/30 Python
工程力学专业毕业生求职信
2013/10/06 职场文书
技校个人求职信范文
2014/01/25 职场文书
百年校庆节目主持词
2014/03/27 职场文书
初三开学计划书
2014/04/27 职场文书
市场开发计划书
2014/05/07 职场文书
融资合作协议书范本
2014/10/17 职场文书
酒店前台岗位职责
2015/04/16 职场文书
罚款通知怎么写
2015/04/22 职场文书
Apache POI操作批量导入MySQL数据库
2022/06/21 Servers