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 相关文章推荐
JS版的date函数(和PHP的date函数一样)
May 12 Javascript
JS实现控制表格只显示行边框或者只显示列边框的方法
Mar 31 Javascript
JS简单设置下拉选择框默认值的方法
Aug 20 Javascript
JS实现购物车特效
Feb 02 Javascript
jQuery选择器之子元素选择器详解
Sep 18 jQuery
使用Vue完成一个简单的todolist的方法
Dec 01 Javascript
Node.js Express安装与使用教程
May 11 Javascript
关于vue项目中搜索节流的实现代码
Sep 17 Javascript
原生js实现随机点餐效果
Dec 10 Javascript
js实现打字小游戏
Dec 17 Javascript
JavaScript实现HTML导航栏下拉菜单
Nov 25 Javascript
vue本地构建热更新卡顿的问题“75 advanced module optimization”完美解决方案
Aug 05 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
mysql下创建字段并设置主键的php代码
2010/05/16 PHP
PHP 获取MySQL数据库里所有表的实现代码
2011/07/13 PHP
关于使用key/value数据库redis和TTSERVER的心得体会
2013/06/28 PHP
php 模拟 asp.net webFrom 按钮提交事件的思路及代码
2013/12/02 PHP
php 判断字符串中是否包含html标签
2014/02/17 PHP
ThinkPHP实现多数据库连接的解决方法
2014/07/01 PHP
PHP多个文件上传到服务器实例
2014/10/29 PHP
Zend Framework上传文件重命名的实现方法
2016/11/25 PHP
thinkPHP5.1框架路由::get、post请求简单用法示例
2019/05/06 PHP
jQuery通过点击行来删除HTML表格行的实现示例
2014/09/10 Javascript
使用不同的方法结合/合并两个JS数组
2014/09/18 Javascript
Node.js 的异步 IO 性能探讨
2014/10/08 Javascript
JS实现网页滚动条感应鼠标变色的方法
2015/02/26 Javascript
在JavaScript中call()与apply()区别
2016/01/22 Javascript
JS显示日历和天气的方法
2016/03/01 Javascript
js提交form表单,并传递参数的实现方法
2016/05/25 Javascript
Bootstrap 源代码分析(未完待续)
2016/08/17 Javascript
JS常用加密编码与算法实例总结
2016/12/22 Javascript
js实现仿购物车加减效果
2017/03/01 Javascript
js仿拉勾网首页穿墙广告效果
2017/03/08 Javascript
JavaScript仿微信打飞机游戏
2020/07/05 Javascript
Angular 4依赖注入学习教程之ClassProvider的使用(三)
2017/06/04 Javascript
微信小程序实现选项卡功能
2020/06/19 Javascript
javascript用rem来做响应式开发
2018/01/13 Javascript
使用vue如何构建一个自动建站项目
2018/02/05 Javascript
微信小程序封装自定义弹窗的实现代码
2019/05/08 Javascript
JavaScript 严格模式(use strict)用法实例分析
2020/03/04 Javascript
LRUCache的实现原理及利用python实现的方法
2017/11/21 Python
NumPy 数组使用大全
2019/04/25 Python
编写python代码实现简单抽奖器
2020/10/20 Python
matplotlib实现数据实时刷新的示例代码
2021/01/05 Python
CSS3教程(5):网页背景图片
2009/04/02 HTML / CSS
超市实习总结自我鉴定
2013/09/19 职场文书
大学生应聘求职信
2014/05/26 职场文书
python之基数排序的实现
2021/07/26 Python
苹果可能正在打击不进行更新的 App
2022/04/24 数码科技