发表于: 2017-04-26 21:23:28

1 991


今天完成的事情:

给进度表格添加angularjs代码,并进行数据绑定,使用$http上传图片。

并查看理解$watch ,$apply 和 $digest --- 理解数据绑定过程。

明天计划的事情:

学习指令,试着把图片上传过程封装成一个组件,写任务10需要的页面,学习正则表达式。

遇到的问题:

1、上传图片时,进度表格里面的数据没有更新,后来知道是因为用的onchange事件,这是js的事件,它没有跟angular的数据同步,之后在函数中调用了$appy,然后就好了。

2、formdata传给服务器的时候总是提示500,到现在都不知道为啥。

收获:

$watch $apply $digest --- 理解数据绑定过程

我们的浏览器一直在等待事件,比如用户交互。假如点击一个按钮或者在输入框里输入东西,事件的回调函数就会在javascript解释器里执行,然后就可以做任何DOM操作,等回调函数执行完毕时,浏览器就会相应地对DOM做出变化。 Angular拓展了这个事件循环,生成一个成为angular context的执行环境。

$watch 队列($watch list):

每次绑定一些东西到UI上时你就会往$watch队列里插入一条$watch。想象一下$watch就是那个可以检测它监视的model里有变化的东西。每一个绑定到了UI上的数据都会生成一个$watch。当模版加载完毕时,也就是在linking阶段(Angular分为compile阶段和linking阶段),Angular解释器会寻找每个directive,然后生成每个需要的$watch。

$digest循环:

当浏览器接收到可以被angular context处理的事件时,$digest循环就会触发。这个循环是由两个更小的循环组合起来的。一个处理evalAsync队列,另一个处理$watch队列, 这个是处理什么的呢?$digest将会遍历我们的$watch,然后询问:

嘿,$watch,你的值是什么?   

        9。

好的,它改变过吗?

        没有,先生。

(这个变量没变过,那下一个)

你呢,你的值是多少?

        报告,是Foo。

刚才改变过没?

        改变过,刚才是Bar。

(很好,我们有DOM需要更新了)

继续询问知道$watch队列都检查过。

这就是所谓的dirty-checking。既然所有的$watch都检查完了,那就要问了:有没有$watch更新过?如果有至少一个更新过,这个循环就会再次触发,直到所有的$watch都没有变化。这样就能够保证每个model都已经不会再变化。如果循环超过10次的话,它将会抛出一个异常,防止无限循环。 当$digest循环结束时,DOM相应地变化。

这里很重要的是每一个进入angular context的事件都会执行一个$digest循环,也就是说每次输入一个字母循环都会检查整个页面的所有$watch。例如:

{{ name }}<button ng-click="changeFoo()">Change the name</button>

app.controller('MainCtrl', function() {

  $scope.name = "Foo";

  $scope.changeFoo = function() {

      $scope.name = "Bar";

  }});

通过$apply来进入angular context:

当事件触发时,调用$apply,它会进入angular context,如果没有调用就不会进入。因此上面的例子点击带有ng-click的元素时,事件就会被封装到一个$apply调用。如果有一个ng-model="foo"的输入框,然后敲一个f,事件就会这样调用$apply("foo = 'f';")

Angular什么时候不会自动为我们调用$apply呢?

为什么jQuery不会更新我绑定的东西呢?因为jQuery没有调用$apply,事件没有进入angular context,$digest循环永远没有执行。这种情况下就要执行$apply,如: scope.$apply();

$apply是$scope(或者是direcvie里的link函数中的scope)的一个函数,调用它会强制一次$digest循环(除非当前正在执行循环,这种情况下会抛出一个异常,这是我们不需要在那里执行$apply的标志)。

使用$watch来监视你自己的东西

你已经知道了我们设置的任何绑定都有一个它自己的$watch,当需要时更新DOM,但是我们如果要自定义自己的watches呢?例如:

app.controller('MainCtrl', function($scope) {

  $scope.name = "Angular";

  $scope.updated = -1;

  $scope.$watch('name', function() {

    $scope.updated++;

  });});

<body ng-controller="MainCtrl">

  <input ng-model="name" />

  Name updated: {{updated}} times.</body>

这就是创造一个新的$watch的方法。第一个参数是一个字符串或者函数,在这里是只是一个字符串,就是要监视的变量的名字,在这里,$scope.name(注意只需要用name)。第二个参数是当$watch说监视的表达式发生变化后要执行的。我们要知道的第一件事就是当controller执行到这个$watch时,它会立即执行一次,因此我们设置updated为-1。



返回列表 返回列表
评论

    分享到