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 相关文章推荐
JavaScript 计算图片加载数量的代码
Jan 01 Javascript
用html5 js实现点击一个按钮达到浏览器全屏效果
May 28 Javascript
Javascript学习笔记之 对象篇(四) : for in 循环
Jun 24 Javascript
jQuery深拷贝Json对象简单示例
Jul 06 Javascript
Node.js中防止错误导致的进程阻塞的方法
Aug 11 Javascript
AngularJS中isolate scope的用法分析
Nov 22 Javascript
Bootstrap Table使用整理(四)之工具栏
Jun 09 Javascript
使用Vue写一个datepicker的示例
Jan 27 Javascript
浅析Vue中method与computed的区别
Mar 06 Javascript
使用Vue实现简单计算器
Feb 25 Javascript
原生JS实现贪吃蛇小游戏
Mar 09 Javascript
vue-router路由懒加载及实现的3种方式
Feb 28 Vue.js
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
PHP4实际应用经验篇(2)
2006/10/09 PHP
php 根据url自动生成缩略图并处理高并发问题
2014/01/23 PHP
ThinkPHP3.1新特性之Action参数绑定
2014/06/19 PHP
php获取文章内容第一张图片的方法示例
2017/07/03 PHP
Yii框架参数配置文件params用法实例分析
2019/09/11 PHP
浅谈JavaScript中面向对象技术的模拟
2006/09/25 Javascript
鼠标滚轮改变图片大小的示例代码
2013/11/20 Javascript
jquery实现聚光灯效果的方法
2015/02/06 Javascript
60行js代码实现俄罗斯方块
2015/03/31 Javascript
javascript瀑布流式图片懒加载实例
2020/06/28 Javascript
JS动态添加选项案例分析
2016/10/17 Javascript
利用 spin.js 生成等待效果(js 等待效果)
2017/06/25 Javascript
Vue 中使用 CSS Modules优雅方法
2018/04/09 Javascript
[09:22]2014DOTA2西雅图国际邀请赛 主赛事第二日TOPPLAY
2014/07/21 DOTA
python网络编程之UDP通信实例(含服务器端、客户端、UDP广播例子)
2014/04/25 Python
Python中Random和Math模块学习笔记
2015/05/18 Python
python黑魔法之编码转换
2016/01/25 Python
Python中的defaultdict与__missing__()使用介绍
2018/02/03 Python
python 集合 并集、交集 Series list set 转换的实例
2018/05/29 Python
Python玩转PDF的各种骚操作
2019/05/06 Python
python集合的创建、添加及删除操作示例
2019/10/08 Python
python list多级排序知识点总结
2019/10/23 Python
使用keras根据层名称来初始化网络
2020/05/21 Python
video实现有声音自动播放的实现方法
2020/05/20 HTML / CSS
瑞贝卡·泰勒官方网站:Rebecca Taylor
2016/09/24 全球购物
世界上最值得信赖的多日游在线市场:TourRadar
2018/07/20 全球购物
澳大利亚在线高跟鞋商店:Shoe Me
2019/11/19 全球购物
金融专业个人求职信
2013/09/22 职场文书
物流专业大学生求职信范文
2013/10/28 职场文书
自主招生推荐信范文
2014/05/10 职场文书
自愿解除劳动合同协议书
2014/09/11 职场文书
作风建设剖析材料
2014/10/06 职场文书
开展党的群众路线教育实践活动剖析材料
2014/10/13 职场文书
会计岗位工作总结
2015/08/12 职场文书
幼儿教师三分钟演讲稿
2019/06/21 职场文书
【海涛教你打dota】体验一超神发条:咱是抢盾专业户
2022/04/01 DOTA