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 相关文章推荐
js报错 Object doesn't support this property or method的原因分析
Mar 31 Javascript
java和javascript获取word文档的书签位置对比
Jun 19 Javascript
jQuery查看选中对象HTML代码的方法
Jun 17 Javascript
D3.js实现雷达图的方法详解
Sep 22 Javascript
JS/jquery实现一个网页内同时调用多个倒计时的方法
Apr 27 jQuery
JavaScript使用享元模式实现文件上传优化操作示例
Aug 07 Javascript
vue解决弹出蒙层滑动穿透问题的方法
Sep 22 Javascript
深入探讨JavaScript的最基本部分之执行上下文
Feb 12 Javascript
javascript中call,apply,callee,caller用法实例分析
Jul 24 Javascript
微信小程序 子级页面返回父级并把子级参数带回父级实现方法
Aug 22 Javascript
layer实现登录弹框,登录成功后关闭弹框并调用父窗口的例子
Sep 11 Javascript
Js代码中的span拼接问题解决
Nov 22 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
浅析Yii中使用RBAC的完全指南(用户角色权限控制)
2013/06/20 PHP
Yii中的cookie的发送和读取
2016/07/27 PHP
php libevent 功能与使用方法详解
2020/03/04 PHP
jQuery 渐变下拉菜单
2009/12/15 Javascript
jquery调用asp.net 页面后台的实现代码
2011/04/27 Javascript
图片img的src不变让浏览器重新加载实现方法
2013/03/29 Javascript
node+express+jade制作简单网站指南
2014/11/26 Javascript
JavaScript动态修改弹出窗口大小的方法
2015/04/06 Javascript
20分钟成功编写bootstrap响应式页面 就这么简单
2016/05/12 Javascript
jQuery实现可拖拽3D万花筒旋转特效
2017/01/03 Javascript
JavaScript中动态向表格添加数据
2017/01/24 Javascript
基于vue的换肤功能的示例代码
2017/10/10 Javascript
JS无限级导航菜单实现方法
2019/01/05 Javascript
JS中的防抖与节流及作用详解
2019/04/01 Javascript
layui 解决富文本框form表单提交为空的问题
2019/10/26 Javascript
微信小程序实用代码段(收藏版)
2019/12/17 Javascript
javascript设计模式 ? 享元模式原理与用法实例分析
2020/04/15 Javascript
手把手带你搭建一个node cli的方法示例
2020/08/07 Javascript
JavaScript实现随机点名小程序
2020/10/29 Javascript
Js数组扁平化实现方法代码总汇
2020/11/11 Javascript
[14:00]DOTA2国际邀请赛史上最长大战 赛后专访B神
2013/08/10 DOTA
浅谈pyhton学习中出现的各种问题(新手必看)
2017/05/17 Python
没编程基础可以学python吗
2020/06/17 Python
HTML5 embed 标签使用方法介绍
2013/08/13 HTML / CSS
英国演唱会订票网站:Ticket Selection
2018/03/27 全球购物
租租车:国际租车、美国租车、欧洲租车、特价预订国外租车(中文服务)
2018/03/28 全球购物
俄罗斯香水在线商店:AromaCode
2019/12/04 全球购物
JAVA招聘远程笔试题
2015/07/23 面试题
建筑毕业生自我鉴定
2013/10/18 职场文书
工作中个人的自我评价
2013/12/31 职场文书
运动会获奖感言
2014/02/11 职场文书
三项教育活动实施方案
2014/03/30 职场文书
后备干部培训方案
2014/05/22 职场文书
2014年行政助理工作总结
2014/11/19 职场文书
2014年政工师工作总结
2014/12/18 职场文书
教你用python实现12306余票查询
2021/06/30 Python