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 相关文章推荐
学习ExtJS Column布局
Oct 08 Javascript
分享20款好玩的jQuery游戏
Apr 17 Javascript
让你的CSS像Jquery一样做筛选的实现方法
Jul 10 Javascript
js检测网络是否具体连接功能的代码
May 23 Javascript
js调试系列 控制台命令行API使用方法
Jun 18 Javascript
jQuery实用密码强度检测
Mar 02 Javascript
Cropper.js 实现裁剪图片并上传(PC端)
Aug 20 Javascript
jquery插件开发之选项卡制作详解
Aug 30 jQuery
9种改善AngularJS性能的方法
Nov 28 Javascript
vue-router 起步步骤详解
Mar 26 Javascript
vue自定义表单生成器form-create使用详解
Jul 19 Javascript
jquery ajax 请求小技巧实例分析
Nov 11 jQuery
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/07/05 PHP
linux环境apache多端口配置虚拟主机的方法深入介绍
2013/06/09 PHP
PHP+AJAX 投票器功能
2017/11/11 PHP
JQuery 操作Javascript对象和数组的工具函数小结
2010/01/22 Javascript
javascript学习笔记(六) Date 日期类型
2012/06/19 Javascript
JS控制文本框textarea输入字数限制的方法
2013/06/17 Javascript
js 加密压缩出现bug解决方案
2014/11/25 Javascript
jquery 构造函数在表单提交过程中修改数据
2015/05/25 Javascript
原生js实现电商侧边导航效果
2017/01/19 Javascript
BootStrap表单宽度设置方法
2017/03/10 Javascript
Vue-cli 使用json server在本地模拟请求数据的示例代码
2017/11/02 Javascript
在vue中使用jointjs的方法
2018/03/24 Javascript
Vue的watch和computed方法的使用及区别介绍
2018/09/06 Javascript
vue自定义指令的创建和使用方法实例分析
2018/12/04 Javascript
React 全自动数据表格组件——BodeGrid的实现思路
2019/06/12 Javascript
详解vuejs中执行npm run dev出现页面cannot GET/问题
2020/04/26 Javascript
Node.js文本文件BOM头的去除方法
2020/11/22 Javascript
Pycharm学习教程(1) 定制外观
2017/05/02 Python
Python中定时任务框架APScheduler的快速入门指南
2017/07/06 Python
Python基于TCP实现会聊天的小机器人功能示例
2018/04/09 Python
tensorflow 打印内存中的变量方法
2018/07/30 Python
简单介绍python封装的基本知识
2019/08/10 Python
使用Python给头像戴上圣诞帽的图像操作过程解析
2019/09/20 Python
Django-Scrapy生成后端json接口的方法示例
2020/10/06 Python
彻底弄明白CSS3的Media Queries(跨平台设计)
2010/07/27 HTML / CSS
lululemon美国官网:瑜伽服+跑步装备
2018/11/16 全球购物
应届毕业生求职信范例分享
2013/12/17 职场文书
违反工作纪律检讨书
2014/02/15 职场文书
大型会议接待方案
2014/03/01 职场文书
怎样拟定创业计划书
2014/05/01 职场文书
搞笑的爱情检讨书
2014/10/01 职场文书
酒会开场白大全
2015/06/01 职场文书
推广普通话宣传标语口号
2015/12/26 职场文书
Pandas数据类型之category的用法
2021/06/28 Python
redis数据一致性的实现示例
2022/03/18 Redis
vue3.0 数字翻牌组件的使用方法详解
2022/04/20 Vue.js