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来处理图片坏链具体实现步骤
May 02 Javascript
javascript获取web应用根目录的方法
Feb 12 Javascript
javasciprt下jquery函数$.post执行无响应的解决方法
Mar 13 Javascript
js控制当再次点击按钮时的间隔时间
Jun 03 Javascript
javascript获取元素偏移量的方法有哪些
Jun 24 Javascript
Jquery网页内滑动缓冲导航的实现代码
Apr 05 Javascript
js如何获取网页所有图片
May 12 Javascript
angularJs中跳转到指定的锚点实例($anchorScroll)
Aug 31 Javascript
微信小程序车牌号码模拟键盘输入功能的实现代码
Nov 11 Javascript
详解vue移动端项目代码拆分记录
Mar 15 Javascript
浅析JavaScript异步代码优化
Mar 18 Javascript
JavaScript正则表达式验证登录实例
Mar 18 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
Protoss兵种介绍
2020/03/14 星际争霸
PHP中文乱码解决方案
2015/03/05 PHP
二行代码解决全部网页木马
2008/03/28 Javascript
jQuery $.data()方法使用注意细节
2012/12/31 Javascript
Jquery 的outerHeight方法使用介绍
2013/09/11 Javascript
extJS中常用的4种Ajax异步提交方式
2014/03/07 Javascript
js鼠标滑过图片震动特效的方法
2015/02/17 Javascript
JavaScript操作DOM元素的childNodes和children区别
2015/04/01 Javascript
浅谈javascript运算符——条件,逗号,赋值,()和void运算符
2016/07/15 Javascript
JS清除字符串中重复值的实现方法
2016/08/03 Javascript
Javascript中call,apply,bind方法的详解与总结
2016/12/12 Javascript
详解NodeJs支付宝移动支付签名及验签
2017/01/06 NodeJs
vue.js事件处理器是什么
2017/03/20 Javascript
Vue服务端渲染和Vue浏览器端渲染的性能对比(实例PK )
2017/03/31 Javascript
关于Bootstrap按钮组件消除黄框的方法
2017/05/19 Javascript
关于vue-router的beforeEach无限循环的问题解决
2017/09/09 Javascript
Angular搜索 过滤 批量删除 添加 表单验证功能集锦(实例代码)
2017/10/25 Javascript
Vue实现动态添加或者删除对象和对象数组的操作方法
2018/09/21 Javascript
小程序页面动态配置实现方法
2019/02/05 Javascript
小程序外卖订单界面的示例代码
2019/12/30 Javascript
[12:51]71泪洒现场!是DOTA2让经典重现
2014/03/24 DOTA
[04:03]辉夜杯主赛事 12月25日RECAP精彩回顾
2015/12/26 DOTA
[49:21]TNC vs VG 2019DOTA2国际邀请赛淘汰赛 胜者组赛BO3 第三场 8.20.mp4
2019/08/22 DOTA
python 自定义异常和异常捕捉的方法
2018/10/18 Python
对python中list的拷贝与numpy的array的拷贝详解
2019/01/29 Python
在python shell中运行python文件的实现
2019/12/21 Python
python pyecharts 实现一个文件绘制多张图
2020/05/13 Python
python+excel接口自动化获取token并作为请求参数进行传参操作
2020/11/10 Python
PAUL HEWITT手表美国站:德国北部时尚生活配饰品牌,船锚元素
2017/11/18 全球购物
Herve Leger官网:标志性绷带连衣裙等
2018/12/26 全球购物
天猫某品牌专卖店运营计划书
2014/03/21 职场文书
写作之关于描写老人的好段摘抄
2019/11/14 职场文书
python制作图形界面的2048游戏, 基于tkinter
2021/04/06 Python
MySql 8.0及对应驱动包匹配的注意点说明
2021/06/23 MySQL
《艾尔登法环》1.03.3补丁上线 碎星伤害调整
2022/04/06 其他游戏
Nginx配置使用详解
2022/07/07 Servers