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 相关文章推荐
不使用XMLHttpRequest实现异步加载 Iframe和script
Oct 29 Javascript
jQuery中RadioButtonList的功能及用法实例介绍
Aug 23 Javascript
js获取页面description的方法
May 21 Javascript
js实现新浪微博首页效果
Oct 16 Javascript
Javascript实现跑马灯效果的简单实例
May 31 Javascript
15款最好的Bootstrap在线编辑器
Aug 03 Javascript
谈谈因Vue.js引发关于getter和setter的思考
Dec 02 Javascript
详解JS去重及字符串奇数位小写转大写
Dec 29 Javascript
Angular 4中如何显示内容的CSS样式示例代码
Nov 06 Javascript
javascript变量提升和闭包理解
Mar 12 Javascript
webpack 处理CSS资源的实现
Sep 27 Javascript
Vue 样式切换及三元判断样式关联操作
Aug 09 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 第二节 数据类型之数值型
2012/04/28 PHP
php实现文件下载代码分享
2014/08/19 PHP
php实现模拟post请求用法实例
2015/07/11 PHP
PHP静态方法和静态属性及常量属性的区别与介绍
2019/03/22 PHP
微信支付之JSAPI公众号支付详解
2019/05/15 PHP
discuz论坛更换域名,详细文件修改步骤
2020/12/09 PHP
extjs3 combobox取value和text案例详解
2013/02/06 Javascript
JavaScript encodeURI 和encodeURIComponent
2015/12/04 Javascript
不用一句js代码初始化组件
2016/01/27 Javascript
js中使用使用原型(prototype)定义方法的好处详解
2016/07/04 Javascript
RequireJS简易绘图程序开发
2016/10/28 Javascript
基于Jquery Ajax type的4种类型(详解)
2017/08/02 jQuery
vue与vue-i18n结合实现后台数据的多语言切换方法
2018/03/08 Javascript
React如何避免重渲染
2018/04/10 Javascript
详解Vue项目引入CreateJS的方法(亲测可用)
2019/05/30 Javascript
详解Angular cli配置过程记录
2019/11/07 Javascript
js实现带搜索功能的下拉框
2020/01/11 Javascript
写给新手同学的vuex快速上手指北小结
2020/04/14 Javascript
[25:59]Newbee vs TNC 2018国际邀请赛小组赛BO2 第二场 8.16
2018/08/17 DOTA
python通过urllib2爬网页上种子下载示例
2014/02/24 Python
用Python实现一个简单的能够上传下载的HTTP服务器
2015/05/05 Python
python多线程http压力测试脚本
2019/06/25 Python
python读csv文件时指定行为表头或无表头的方法
2019/06/26 Python
Python Selenium 设置元素等待的三种方式
2020/03/18 Python
查看keras各种网络结构各层的名字方式
2020/06/11 Python
Html5移动端网页端适配(js+rem)
2021/02/03 HTML / CSS
服装销售人员求职自我评价
2013/09/26 职场文书
运动会通讯稿400字
2014/01/28 职场文书
亲子读书活动方案
2014/02/22 职场文书
小学生操行评语
2014/04/22 职场文书
根叔历年演讲稿
2014/05/20 职场文书
商场周年庆活动方案
2014/08/19 职场文书
处级干部考察材料
2014/12/24 职场文书
2015年体检中心工作总结
2015/05/27 职场文书
导游词之平津战役纪念馆
2019/11/04 职场文书
ThinkPHP5和ThinkPHP6的区别
2021/03/31 PHP