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原创弹出层折叠效果点击折叠弹出一个层
Mar 12 Javascript
jquery让返回的内容显示在特定div里(代码少而精悍)
Jun 23 Javascript
基于Flowplayer打造一款免费的WEB视频播放器附源码
Sep 06 Javascript
纯js代码实现未知宽高的元素在指定元素中垂直水平居中显示
Sep 12 Javascript
Javascript实现单例模式
Jan 24 Javascript
jQuery+css实现的切换图片功能代码
Jan 27 Javascript
聊一聊JavaScript作用域和作用域链
May 03 Javascript
JavaScript知识点总结(十六)之Javascript闭包(Closure)代码详解
May 31 Javascript
全面了解函数声明与函数表达式、变量提升
Aug 09 Javascript
Vue 框架之动态绑定 css 样式实例分析
Nov 14 Javascript
Vue路由切换页面不更新问题解决方案
Jul 10 Javascript
解决idea开发遇到javascript动态添加html元素时中文乱码的问题
Sep 29 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无限分类的类
2007/01/02 PHP
需要使用php模板的朋友必看的很多个顶级PHP模板引擎比较分析
2008/05/26 PHP
解析crontab php自动运行的方法
2013/06/24 PHP
WordPress主题中添加文章列表页页码导航的PHP代码实例
2015/12/22 PHP
用JQuery 实现AJAX加载XML并解析的脚本
2009/07/25 Javascript
JavaScript DOM 学习第三章 内容表格
2010/02/19 Javascript
javascript 数据类型转换(parseInt,parseFloat)
2010/07/20 Javascript
jQuery1.3.2 升级到jQuery1.4.4需要修改的地方
2011/01/06 Javascript
背景图跟随鼠标移动的Mootools插件实现代码
2011/12/12 Javascript
Jquery实现列表(隔行换色,全选,鼠标滑过当前行)效果实例
2013/06/09 Javascript
javascript图片预加载实例分析
2015/07/16 Javascript
JS实现图片平面旋转的方法
2016/03/01 Javascript
js 动态添加元素(div、li、img等)及设置属性的方法
2016/07/19 Javascript
Javascript日期格式化format函数的使用方法
2016/08/30 Javascript
JS实现仿UC浏览器前进后退效果的实例代码
2017/07/17 Javascript
js传递数组参数到后台controller的方法
2018/03/29 Javascript
vue项目中使用百度地图的方法
2018/06/08 Javascript
微信小程序支付前端源码
2018/08/29 Javascript
自己动手封装一个React Native多级联动
2018/09/19 Javascript
通过js给网页加上水印背景实例
2019/06/17 Javascript
vue搜索页开发实例代码详解(热门搜索,历史搜索,淘宝接口演示)
2020/04/11 Javascript
[03:03]2014DOTA2国际邀请赛 EG战队专访
2014/07/12 DOTA
Python使用回溯法子集树模板解决迷宫问题示例
2017/09/01 Python
Python实现将HTML转成PDF的方法分析
2019/05/04 Python
python pickle存储、读取大数据量列表、字典数据的方法
2019/07/07 Python
python GUI框架pyqt5 对图片进行流式布局的方法(瀑布流flowlayout)
2020/03/12 Python
Python调用接口合并Excel表代码实例
2020/03/31 Python
个人工作主要事迹
2014/05/08 职场文书
细节决定成败演讲稿
2014/05/12 职场文书
平安家庭示范户事迹
2014/06/02 职场文书
市场策划求职信
2014/08/07 职场文书
一般基层干部群众路线教育实践活动个人对照检查材料
2014/11/04 职场文书
2015小学语文教师个人工作总结
2015/05/20 职场文书
业务员年终工作总结2015
2015/05/28 职场文书
大队委员竞选演讲稿
2015/11/20 职场文书
SQL基础的查询语句
2021/11/11 MySQL