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仿PS里的羽化效果代码
Dec 20 Javascript
jQuery中appendTo()方法用法实例
Jan 08 Javascript
js图片卷帘门导航菜单特效代码分享
Sep 10 Javascript
DeviceOne 让你一见钟情的App快速开发平台
Feb 17 Javascript
EasyUI闪屏EasyUI页面加载提示(原理+代码+效果图)
Feb 21 Javascript
Bootstrap Validator 表单验证
Jul 25 Javascript
jQuery解析XML 详解及方法总结
Sep 28 Javascript
简单谈谈关于Angular Cli打包的事
Sep 05 Javascript
vue将单页面改造成多页面应用的方法
Nov 25 Javascript
详解Node.js一行命令上传本地文件到服务器
Apr 22 Javascript
gulp构建小程序的方法步骤
May 31 Javascript
如何自定义微信小程序tabbar上边框的颜色
Jul 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
Codeigniter+PHPExcel实现导出数据到Excel文件
2014/06/12 PHP
php禁止某ip或ip地址段访问的方法
2015/02/25 PHP
PHP中substr_count()函数获取子字符串出现次数的方法
2016/01/07 PHP
浅析Yii2 GridView实现下拉搜索教程
2016/04/22 PHP
Laravel 验证码认证学习记录小结
2019/12/20 PHP
实现连缀调用的map方法(prototype)
2009/08/05 Javascript
javascript 判断字符串是否包含某字符串及indexOf使用示例
2013/10/18 Javascript
浅析jQuery EasyUI中的tree使用指南
2014/12/18 Javascript
javascript 兼容各个浏览器的事件
2015/02/04 Javascript
C++中的string类的用法小结
2015/08/07 Javascript
javascript如何实现暂停功能
2015/11/06 Javascript
jquery分页插件jquery.pagination.js使用方法解析
2016/04/01 Javascript
JavaScript中日期函数的相关操作知识
2016/08/03 Javascript
JavaScript实现大图轮播效果
2017/01/11 Javascript
Nodejs进阶:express+session实现简易登录身份认证
2017/04/24 NodeJs
Vue+axios 实现http拦截及路由拦截实例
2017/04/25 Javascript
JAVA面试题 static关键字详解
2019/07/16 Javascript
[02:30]DOTA2放量测试专访海涛:呼吁保护新手玩家
2013/08/26 DOTA
python获取文件版本信息、公司名和产品名的方法
2014/10/05 Python
在Python下进行UDP网络编程的教程
2015/04/29 Python
利用python程序帮大家清理windows垃圾
2017/01/15 Python
Python爬虫实现百度图片自动下载
2018/02/04 Python
cmd运行python文件时对结果进行保存的方法
2018/05/16 Python
Python设计模式之适配器模式原理与用法详解
2019/01/15 Python
手把手教你使用Python创建微信机器人
2019/04/29 Python
Python 从subprocess运行的子进程中实时获取输出的例子
2019/08/14 Python
通过python3实现投票功能代码实例
2019/09/26 Python
Pyecharts绘制全球流向图的示例代码
2020/01/08 Python
Python3实现打印任意宽度的菱形代码
2020/04/12 Python
HTML5如何为形状图上颜色怎么绘制具有颜色和透明度的矩形
2014/06/23 HTML / CSS
GOOD AMERICAN官网:为曲线性感而设计
2017/12/28 全球购物
乌克兰机票、铁路和巴士票、酒店搜索、保险:Tickets.ua
2020/01/11 全球购物
美国户外服装和装备购物网站:Outland USA
2020/03/22 全球购物
廉洁家庭事迹材料
2014/05/15 职场文书
解决pycharm安装scrapy DLL load failed:找不到指定的程序的问题
2021/06/08 Python
科学家研发出新型速效酶,可在 24 小时内降解塑料制品
2022/04/29 数码科技