您好,欢迎来到三六零分类信息网!老站,搜索引擎当天收录,欢迎发信息
免费发信息
三六零分类信息网 > 海口分类信息网,免费分类信息发布

AngularJS脏检查机制及$timeout的妙用

2024/3/3 10:52:50发布31次查看
本篇文章主要介绍了详解angularjs脏检查机制及$timeout的妙用,“脏检查”是angular中的核心机制之一,它是实现双向绑定、mvvm模式的重要基础,有兴趣的可以了解一下
||浏览器事件循环和angular的mvw
“脏检查”是angular中的核心机制之一,它是实现双向绑定、mvvm模式的重要基础。
angular将双向绑定转换为一堆watch表达式,然后递归检查这些watch表达式的结果是否变了,如果变了,则执行相应的watcher函数。等到model的值不再变化,也就不会再有watcher函数被触发,一个完整的digest循环就结束了。
因为我们不需要改变编程思维,就能用相同的语言、相同的事件模型,快速开发nodejs程序,所以nodejs迅速火起来,javascript full-stack也日渐流行。
我们经常听说angular是一个mv*的框架,这是因为angular拓展了浏览器的事件模型,建立了一个自己的上下文环境。
||angular中的$watch函数
watch表达式很灵活:可以是一个函数,可以是$scope上的一个属性名,也可以是一个字符串形式的表达式。$scope上的属性名或表达式,最终仍会被$parse服务解析为响应的获取属性值的函数。
所有的watcher函数都会被unshift函数插入scope.$$watchers数组的头部,以便后边的$digest使用。
最后,$watch函数会返回一个反注册函数,一旦我们调用它,就可以移除刚才注册的watcher。
需要注意的是,angular默认是不会使用angular.equals()函数进行深度比较的,因为使用===比较会更快,所以,它对数组或者object进行比较时检查的是引用。这就导致内容完全相同的两个表达式被判定为不同。如果需要进行深度比较,第三个可选参数objectequality,需要显式设置为true,如$watch('someexp', function(){...}, true)。
angular还提供了$watchgroup、$watchcollection方法来监听数组或者是一组属性。
||angular中的$digest函数
前面提到angular拓展了浏览器的事件循环,这是怎么回事呢?
当接受view上的事件指令所转发的事件时,就会切换到angular的上下文环境,来相应这类事件,$digest循环就会触发。
$digest循环实际上包括两个while循环。它们分别是:处理$evalasync的异步运算队列,处理$watch的watchers队列。
当$digest循环发生的时候,它会遍历当前$scope及其所有子$scope上已注册的所有watchers函数。
遍历一遍所有watcher函数称为一轮脏检查。执行完一轮脏检查,如果任何一个watcher所监听的值改变过,那么就会重新再进行一轮脏检查,直到所有的watcher函数都报告其所监听的值不再变了。
当$digest循环结束时,才把模型的变化结果更新到dom中去。这样可以合并多个更新,防止频繁的dom属性。
需要注意的是,在$digest循环结束之前,如果超过了10轮脏检查,就会抛出一个异常,以防止脏检查无限循环下去。
什么时候会进入这个angular的上下文环境,触发“脏检查机制”呢?这个问题很重要,它同时也是比较让人头疼的地方。
每一个进入angular上下文环境的事件,都会执行一次$digest循环。对于ngmodel监听的表单交互控件来说,每输入一个字符,就会触发一次循环来检查$watcher函数,以便及时更新view。在angular1.3之后可以利用ngmodeloptions进行配置,来修改默认的触发方式。
||angular中的$apply
$digest是一个内部函数,正常的应用代码中是不应该直接调用它的。要想主动触发它,就要调用scope.$apply函数,它是触发angular“脏检查机制”的常用公开接口。
需要注意的是:angular只能管理它所已知的行为触发方式,而不能涵盖所有的angular操作场景。这就为什么我们在封装第三方jquery插件时,不能自动更新视图,而需要我们手动调用$scope.$apply。
集成jquery插件的时候,有时会出现digest in progress错误。如果排除bug之后仍然不能解决,那么可以考虑用$timeout来解决。
$timeout的妙用
在延时任务中修改被绑定到界面中的变量,那么window.settimeout是不会触发“脏检查”来更新ui界面的。你可能想:加上$scope.$apply不就解决了嘛。是的,这能解决ui界面更新的问题,但是你可能会遇到另一个问题:
error: $digest already in progress
这是怎么回事儿?哦,angular内部正在进行“脏检查”。一位聪明的程序员巧妙地写了下面一段代码来解决这个问题:
function safeapply(scope, fn){ (scope. phase||scope.$root. phase) ? fn() : scope.$apply(fn); }
代码中,在执行apply函数之前会首先检查angular内部是不是正在做“脏检查”,如果是就直接执行函数,不用$apply;反之没有启动脏检查,那么就$apply执行该函数。呵呵,“完美”解决,不是吗?
请注意,笔者在上面的完美两个字上加了引号。angular已经为我们内置了$timeout服务,它是angular包装原生javascript window.settimeout而实现的。
$timeout有很多妙用,但一定不要滥用,$timeout实现apply功能不应该是我们的第一方案,第一方案仍然应该是使用angular内置的指令。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
以上就是angularjs脏检查机制及$timeout的妙用的详细内容。
海口分类信息网,免费分类信息发布

VIP推荐

免费发布信息,免费发布B2B信息网站平台 - 三六零分类信息网 沪ICP备09012988号-2
企业名录