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 相关文章推荐
Jquey拖拽控件Draggable使用方法(asp.net环境)
Sep 28 Javascript
基于Jquery的仿照flash放大图片效果代码
Mar 16 Javascript
15款优秀的jQuery导航菜单插件分享
Jul 19 Javascript
javascript suggest效果 自动完成实现代码分享
Feb 17 Javascript
jquery增加和删除元素的方法
Jan 14 Javascript
JavaScript返回当前会话cookie全部键值对照的方法
Apr 03 Javascript
学习JavaScript设计模式(策略模式)
Nov 26 Javascript
关于JS中的apply,call,bind的深入解析
Apr 05 Javascript
JS 对象(Object)和字符串(String)互转方法
May 20 Javascript
js智能获取浏览器版本UA信息的方法
Aug 08 Javascript
addeventlistener监听scroll跟touch(实例讲解)
Aug 04 Javascript
angular6.0使用教程之父组件通过url传递id给子组件的方法
Jun 30 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结束标签的使用细节探讨及联想
2013/03/04 PHP
php实现三级级联下拉框
2016/04/17 PHP
javascript js cookie的存储,获取和删除
2007/12/29 Javascript
JavaScript 替换Html标签实现代码
2009/10/14 Javascript
js 弹出框只弹一次(二次修改之后的)
2013/11/26 Javascript
js改变文章字体大小的实例代码
2013/11/27 Javascript
js实现圆盘记速表
2015/08/03 Javascript
javascript实现tab响应式切换特效
2016/01/29 Javascript
AngularJs 弹出模态框(model)
2016/04/07 Javascript
基于Bootstrap3表格插件和分页插件实例详解
2016/05/17 Javascript
AngularJS基础 ng-open 指令简单实例
2016/08/02 Javascript
浅谈JavaScript事件绑定的常用方法及其优缺点分析
2016/11/01 Javascript
微信小程序  wx.request合法域名配置详解
2016/11/23 Javascript
将JSON字符串转换成Map对象的方法
2016/11/30 Javascript
js正则表达式验证密码强度【推荐】
2017/03/03 Javascript
JavaScript面向对象精要(上部)
2017/09/12 Javascript
微信小程序实现循环动画效果
2018/07/16 Javascript
jQuery实现的简单歌词滚动功能示例
2019/01/07 jQuery
nodejs环境使用Typeorm连接查询Oracle数据
2019/12/05 NodeJs
JS实现拼图游戏
2021/01/29 Javascript
Vue Object.defineProperty及ProxyVue实现双向数据绑定
2020/09/02 Javascript
jQuery实现手风琴特效
2021/01/11 jQuery
python的几种开发工具介绍
2007/03/07 Python
python计算日期之间的放假日期
2018/06/05 Python
Python3导入CSV文件的实例(跟Python2有些许的不同)
2018/06/22 Python
Django框架的使用教程路由请求响应的方法
2018/07/03 Python
Python pandas如何向excel添加数据
2020/05/22 Python
Python3开发环境搭建详细教程
2020/06/18 Python
使用Python操作MySQL的小技巧
2020/09/10 Python
麦德龙官方海外旗舰店:德国麦德龙超市
2017/12/23 全球购物
小学生演讲稿
2014/01/12 职场文书
广告语设计及教案
2014/03/21 职场文书
政府门卫岗位职责
2014/04/29 职场文书
中标通知书格式
2015/04/17 职场文书
导游词之任弼时故居
2020/01/07 职场文书
关于maven依赖 ${xxx.version}报错问题
2022/01/18 Java/Android