IT修真院·小课堂丨互联网职业小课堂在线学习平台

课堂课题:

angularjs双向绑定后,发生了什么事情?是什么可以让view层和controller层进行绑定的?

关联任务:

任务二

直播时间:

2019-01-13 19:30:00


课堂内容:

视频链接:

PPT链接:

提交按钮:

小课堂内容格式


标题:

【修真院xx(职业)小课堂】课题名称

开场语:

大家好,我是IT修真院XX分院第X期的学员XX,一枚正直纯洁善良的XX程序员,今天给大家分享一下,修真院官网XX(职业)任务X,深度思考中的知识点——XXX

(1)背景介绍:

背景介绍的时候,尽可能的要宽广,讲清楚来龙去脉,讲清楚为什么会需要这个技术。

(2)知识剖析:

讲知识点的时候,尽可能的成体系,学会成体系的去给别人介绍知识。现在很多做的都是零散的,没有分类。

(3)常见问题:

最少列出1个常见问题。

(4)解决方案:

写清楚常见问题的解决方案。

(5)编码实战:

尽可能的去寻找在真实项目中在用的。如果你能找到某个网站在用你说的知识点,这是最好的。学以致用,否则当成练习题就没有意义了。多准备一些demo,讲解过程中将知识点和demo结合,便于大家理解所讲解的知识点。

(6)拓展思考:

知识点之外的拓展思考,由分享人进行讲解,这些东西就是所谓的深度,也是一个人技术水准高低比较的表现。

(7)参考文献:

引入参加文献的时候,在引用的句子后面加上序号【1】。参考文献中列出详细来源。不要去抄别人的东西,这是一个基本的态度。

(8)更多讨论:

Q1:提问人:问题?
A1:回答人(可以是分享人,也可以是其他学员):回答
Q2:提问人:问题?
A2:回答人(可以是分享人,也可以是其他学员):回答
Q3:提问人:问题?
A3:回答人(可以是分享人,也可以是其他学员):回答

(9)鸣谢:

感谢XX、XX师兄,此教程是在他们之前技术分享的基础上完善而成。

(10)结束语:

今天的分享就到这里啦,欢迎大家点赞、转发、留言、拍砖~

angularjs双向绑定后,发生了什么事情?是什么可以让view层和controller层进行绑定的?     中品

辅导师兄 [真传弟子]JS-张林骞


【JS-TASK6】 ANGULARJS双向绑定

分享人:霍亚豪

目录

1.背景介绍

2.知识剖析

3.常见问题

4.解决方案

5.编码实战

6.扩展思考

7.参考文献

8.更多讨论

1.背景介绍

 

双向绑定

Angular实现了双向绑定机制。所谓的双向绑定,无非是从界面的操作能实时反映到数据,数据的变更能实时展现到界面 当 view 中有任何数据变化时,会更新到 model ,当 model 中数据有变化时,view 也会同步更新

2.知识剖析

ANGULARJS SCOPE(作用域)

Scope(作用域)是应用在 HTML (视图)和 JavaScript (控制器)之 间的纽带。Scope是一个对象,有可用的方法和属性。Scope可应用在视图和控制器 上。$scope的使用贯穿整个 Angular App应用,它与数据模型相关联 ,同时也是表达式执行的上下文.有了 $scope就在视图和控制器之间建立 了一个通道,基于作用域视图在修改数据时会立刻更新 $scope,同样的 $s cope发生改变时也会立刻重新渲染视图.

$SCOPE

$scope是一个把view(一个DOM元素)连结到controller上的对象。在我们的MVC结构里,这个 $scope将成为model,它提供一个绑定到DOM元素(以及其子元素)上的excecution context。 $scope实际上就是一个JavaScript对象,controller和view都可以访问它,所以我们可以利用它在两者间传递信息。在这个 $scope对象里,我们既可以存储数据,又可以存储将要运行在view上的函数。

$SCOPE的作用

提供了观察者可以监听数据模型的变化 可以将数据模型的变化通知给整个 App 可以进行嵌套,隔离业务功能和数据 给表达式提供上下文执行环境 在 Javascript中创建一个新的执行上下文,实际就是用函数创建了一个新的本地上下文, 在 Angular中当为子 DOM元素创建新的作用域时,其实就是为子 DOM元素创建了一个新的执行上下文.

 

$WATCH:

angularjs核心之一是双向绑定,那么这个双向绑定是如何实现的呢?  当我们在创建出scope下的一个新属性的时候,ng就会主动为我们新属性注册$watch这个方法,$watch用来监听的数据变化,当数据变化之后,就立即把view和scope上数据同步。AngularJS就能够自动注册并监听变量的改变。AngularJS会首先将在{{ }}中声明的表达式编译成函数并调用$watch方法。  $watch是一个scope函数,用于监听模型变化但是,还存在一个很重要的问题!AngularJS是如何知道什么时候要调用这个回调函数呢?换句话说,AngularJS是如何知晓aModel发生了变化,才调用了对应的回调函数呢?它会周期性的运行一个函数来检查scope模型中的数据是否发生了变化吗?好吧,这就是$digest循环的用武之地了。

$DIGEST

在调用了$scope.$digest()后,$digest循环就开始了。假设你在一个ng-click指令对应的handler函数中更改了scope中的一条数据,此时AngularJS会自动地通过调用$digest()来触发一轮$digest循环。当$digest循环开始后,它会触发每个watcher。这些watchers会检查scope中的当前model值是否和上一次计算得到的model值不同。如果不同,那么对应的回调函数会被执行。调用该函数的结果,就是view中的表达式内容(译注:诸如{{ aModel }})会被更新。除了ng-click指令,还有一些其它的built-in指令以及服务来让你更改models(比如ng-model,$timeout等)和自动触发一次$digest循环。

AngularJS并不直接调用$digest(),而是调用$scope.$apply(),后者会调用$rootScope.$digest()。因此,一轮$digest循 环在$rootScope开始,随后会访问到所有的children scope中的watchers。

例如我们按下按钮触发ng-click事件:
  1、浏览器接收到一个事件,进入angular context。
  2、 $digest循环开始执行,查询每个$watch是否变化。
  3、 由于监视$scope.name的$watch报告了变化,它会强制再执行一次$digest循环。
  4、 新的$digest循环没有检测到变化。
  5、浏览器拿回控制权,更新与$scope.name新值相应部分的DOM。

 

  6、这里重要的是每一个进入angular context{ 我们的浏览器一直在等待事件,比如用户交互。假如你点击一个按钮或者在输入框里输入东西,事件的回调函数就会在javascript解释器里执行,然后你就可以做任何DOM操作,等回调函数执行完毕时,浏览器就会相应地对DOM做出变化。 Angular拓展了这个事件循环,生成一个有时成为angular context的执行环境}的事件都会执行一个$digest循环,也就是说每次我们输入一个字母循环都会检查整个页面的所有$watch。  Angular会为我们自动调用$apply!因此当点击带有ng-click的元素时,事件就会被封装到一个$apply调用。  比如有一个ng-model="foo"的输入框,然后敲一个f,事件就会这样调用$apply("foo = 'f';"),触发$digest循环。

 

3.常见问题

什么时候手动调用$apply()方法?

4 解决方案

如果AngularJS总是将我们的代码wrap到一个function中并传入$apply(),以此来开始一轮$digest循环,那么什么时候才需要我们手动地调用$apply()方法呢?实际上,AngularJS对此有着非常明确的要求,就是它只负责对发生于AngularJS上下文环境中的变更会做出自动地响应(即,在$apply()方法中发生的对于models的更改)。AngularJS的built-in指令就是这样做的,所以任何的model变更都会被反映到view中。但是,如果你在AngularJS上下文之外的任何地方修改了model,那么你就需要通过手动调用$apply()来通知AngularJS。这就像告诉AngularJS,你修改了一些models,希望AngularJS帮你触发watchers来做出正确的响应。

如果你使用了JavaScript中的setTimeout()来更新一个scope model,那么AngularJS就没有办法知道你更改了什么。这种情况下,调用$apply()就是你的责任了,通过调用它来触发一轮$digest循环。类似地,如果你有一个指令用来设置一个DOM事件listener并且在该listener中修改了一些models,那么你也需要通过手动调用$apply()来确保变更会被正确的反映到view中。

 

如果你使用了JavaScript中的setTimeout()来更新一个scope model,那么AngularJS就没有办法知道你更改了什么。这种情况下,调用$apply()就是你的责任了,通过调用它来触发一轮$digest循环。类似地,如果你有一个指令用来设置一个DOM事件listener并且在该listener中修改了一些models,那么你也需要通过手动调用$apply()来确保变更会被正确的反映到view中。

5.编码实战

DEMO

6.扩展思考

$DIGEST循环会运行多少次?

当一个$digest循环运行时,watchers会被执行来检查scope中的models是否发生了变化。如果发生了变化,那么相应的listener函数就会被执行。这涉及到一个重要的问题。如果listener函数本身会修改一个scope model呢?AngularJS会怎么处理这种情况? 答案是$digest循环不会只运行一次。在当前的一次循环结束后,它会再执行一次循环用来检查是否有models发生了变化。这就是脏检查(Dirty Checking),它用来处理在listener函数被执行时可能引起的model变化。 因此,$digest循环会持续运行直到model不再发生变化,或者$digest循环的次数达到了10次。因此,尽可能地不要在listener函数中修改model。 $digest循环最少也会运行两次,即使在listener函数中并没有改变任何model。正如上面讨论的那样,它会多运行一次来确保models没有变化。

 

7.参考文献

https://blog.csdn.net/dm_vincent/article/details/38705099

8 更多讨论


问题一:为什么例五里面自定义指令需要调用$apply方法?是不是自定义指令都不具备$apply方法?

答:不是。不是因为自定义指令本身不具有$apply方法,因为element.on(“click”,function{})这实际上是一个jQuery方法,而jQuery是不具备$apply方法的。如果我们把scope.b++使用一个angular方法去触发,是不用调用$apply就可以触发的。

问题二:前文提到的循环十次会抛出异常,是指什么?

是指在一个ng-指令(本身已经自带$apply方法)内部再次调用$apply方法,就会抛出异常。这实际上是angular的保护机制。

问题三:dirty-checking这么复杂,会不会速度很慢?

不会的,实际上运行的很快。而且在ES6普及后,angular的未来版本会加入Object.observe,$digest循环的速度会更快。


鸣谢

感谢大家观看

BY : 霍亚豪




评论

[郑州|荣耀师兄]JS-宋恒 发表于 2019-01-16 12:12:57 #1

双向绑定的原理讲到了,但是具体的ngmodel,ngbind,表达式 可以再多讲

回复

请您登录 后进行评论