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 相关文章推荐
单击某一段文字改写文本颜色
Jun 06 Javascript
浅析js预加载/延迟加载
Sep 25 Javascript
JavaScript数据推送Comet技术详解
Apr 07 Javascript
浅谈JavaScript中数组的增删改查
Jun 20 Javascript
jQuery中ScrollTo用法示例
Sep 04 Javascript
jquery使用iscorll实现上拉、下拉加载刷新
Oct 26 jQuery
js阻止默认右键的下拉菜单方法
Jan 02 Javascript
在vue项目中引入高德地图及其UI组件的方法
Sep 04 Javascript
Angular事件之不同组件间传递数据的方法
Nov 15 Javascript
jQuery的ztree仿windows文件新建和拖拽功能的实现代码
Dec 05 jQuery
详解vue项目中调用百度地图API使用方法
Apr 25 Javascript
vue基于v-charts封装双向条形图的实现代码
Dec 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获取中英混合字符串长度的方法
2014/06/07 PHP
Laravel 5+ .env环境配置文件详解
2020/04/06 PHP
2020最新版 PhpStudy V8.1版本下载安装使用详解
2020/10/30 PHP
用javascript获取textarea中的光标位置
2008/05/06 Javascript
js window.onload 加载多个函数和追加函数详解
2014/01/08 Javascript
laytpl 精致巧妙的JavaScript模板引擎
2014/08/29 Javascript
轻松创建nodejs服务器(4):路由
2014/12/18 NodeJs
Node.js事件循环(Event Loop)和线程池详解
2015/01/28 Javascript
jquery实现鼠标经过显示下划线的渐变下拉菜单效果代码
2015/08/24 Javascript
jQuery插件实现无缝滚动特效
2015/11/24 Javascript
Vue.js每天必学之组件与组件间的通信
2016/09/08 Javascript
JS按条件 serialize() 对应标签的使用方法
2017/07/24 Javascript
vue .js绑定checkbox并获取、改变选中状态的实例
2018/08/24 Javascript
vue循环数组改变点击文字的颜色
2019/10/14 Javascript
基于vue实现图片验证码倒计时60s功能
2019/12/10 Javascript
[03:21]【TI9纪实】Old Boys
2019/08/23 DOTA
python复制文件代码实现
2013/12/23 Python
python生成指定长度的随机数密码
2014/01/23 Python
python字典DICT类型合并详解
2017/08/17 Python
Python使用字典实现的简单记事本功能示例
2019/08/15 Python
Django后端发送小程序微信模板消息示例(服务通知)
2019/12/17 Python
python GUI库图形界面开发之PyQt5中QWebEngineView内嵌网页与Python的数据交互传参详细方法实例
2020/02/26 Python
结合CSS3的新特性来总结垂直居中的实现方法
2016/05/30 HTML / CSS
HTML5中使用postMessage实现两个网页间传递数据
2016/06/22 HTML / CSS
在线实验室测试:HealthLabs.com
2020/05/03 全球购物
几道PHP的面试题
2012/05/19 面试题
浙大网新C/C++面试解惑
2015/05/27 面试题
行政主管岗位职责
2013/11/18 职场文书
消防器材管理制度
2014/01/28 职场文书
小学庆六一活动总结
2014/08/28 职场文书
户外亲子活动总结
2015/05/08 职场文书
2015年团委副书记工作总结
2015/07/23 职场文书
小学数学教学随笔
2015/08/14 职场文书
三好学生主要事迹怎么写
2015/11/03 职场文书
JAVA SpringMVC实现自定义拦截器
2022/03/16 Python
中国古风插画师排行榜:夏达第一,第三是阴阳师姑获鸟皮肤创作者
2022/03/18 国漫