前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >AngularJS的digest循环和$apply

AngularJS的digest循环和$apply

作者头像
奋飛
发布2019-08-15 10:16:22
3.1K0
发布2019-08-15 10:16:22
举报
文章被收录于专栏:Super 前端Super 前端

最近在写AngularJS,遇到一个问题,在Ajax异步请求后台数据,然后将结果赋值给当前scope中某对象的属性,在页面中怎么都取不到,然而在js端却可以正常打印出来。

分析原因:第一感觉是前端页面绑定指令不对,导致不能正常显示,然而变化各种指令都不能正常获取,很是郁闷;最后去掉Ajax,直接返回给页面,结果却是可以的,初步排除了与绑定指令相关。那问题出现在scope上了???结果查阅资料,终于得知,使用第三方框架(比如jQuery),或者调用setTimeout(),会导致其运行在AngularJS上下文外部,可以使用apply()函数让Angular返回apply()函数让Angular返回digest循环,传递到Angular应用中。

一、传统事件触发

在标准的浏览器流程中,页面加载、$http请求返回响应、鼠标移动以及按钮被点击等情况都会触发事件。当事件被触发时(比如点击一个链接),JavaScript会创建一个事件对象,并执行这个事件对象所在的监听特定事件的所有函数。然后浏览器会执行注册给该事件的回调函数,更新DOM。

注意:同一时间不能运行两个事件。

当使用angular时,其会扩展这个标准的浏览器流程,创建一个angular上下文(angular事件循环内的特定代码,该angular事件循环通常被称为$digest循环)。

二、$digest循环

digest循环有两个主要部分组成:digest循环有两个主要部分组成:watch列表,$evalAsync列表。

1. $watch列表

angular跟踪变化,是通过给watch列表添加一个监控函数做到的,需要注意的是所有绑定给同一watch列表添加一个监控函数做到的,需要注意的是所有绑定给同一scope对象的UI元素,只会添加一个watch到watch到watch列表中。这些watch列表会在watch列表会在digest循环中的“脏值检查”(检测值是否发生了变化,但整个应用还没有同步该变化)的程序解析。 (1)$watch(watchExpression, listener/callback, objectEquality)

(2)$watchCollection(obj/string, listener)

代码语言:javascript
复制
$scope.$watchCollection('names', function(newNames, oldNames, scope) {
    // 发送变化的处理
});

2. $evalAsync列表

$evalAsync()方法是一种在当前作用域上调度表达式在未来某个时刻运行的方式。

指令、控制器调用$evalAsync(),会在angular操作DOM之后,浏览器渲染之前运行。所以,永远不要使用其来约定事件的顺序。

三、页面中的$digest循环

代码语言:javascript
复制
<input type="text" ng-model="user.name" ng-minlength="3" />

(1)angular会设置一个隐式的监控器,将输入字段的值绑定为当前的$scope对象;

(2)当用户输入字符,angular上下文就会生效并开始遍历$$watchers($watch列表);

(3)监控函数在$scope.user.name绑定上执行;

(4)退出$digest循环之前,会触发该值(ng-model)上运行的验证和格式化操作;

(5)由于在digest循环中值发生了变化,angular需要再次运行这一循环以确定它没有改变作用域对象上的其他值。(原因:如果有一个名为scope.user.fullName的属性由scope.user.fullName的属性由scope.user.firstName和$scope.user.lastName组成,那么这两个值的变化多会引起fullName的变化,因此需要再次确认);

(6)$digest循环退出,浏览器重绘DOM以刷新视图。

四、$apply从外部进入上下文

所有指令ng-[event]指令(如ng-click)都会调用scope.scope.apply(),以强制运行$digest循环。

apply()函数可以从angular框架的外部让表达式在angular上下文内部执行。当手动处理事件,使用第三框架(比如jquery)或者调用setTimeout都可以使用apply()函数可以从angular框架的外部让表达式在angular上下文内部执行。当手动处理事件,使用第三框架(比如jquery)或者调用setTimeout都可以使用apply()函数将值传递到angular应用中。

(1)不建议在控制器中使用$apply(),因为这样会导致难以测试。 (2)jquery和angular同时使用被视为一个肮脏的行为。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2015年08月30日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、传统事件触发
  • 二、$digest循环
    • 1. $watch列表
      • 2. $evalAsync列表
      • 三、页面中的$digest循环
      • 四、$apply从外部进入上下文
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档