使用angularjs1.x构建前台开发框架(十二)——脏检查

上一章介绍了数据双向绑定,那么在angularjs1.x版本中是怎么做到这一点的呢?就是依赖Dirty Checking,即本章介绍的脏检查。那么什么是脏检查?简而言之,就是在angularjs作用域内定义的变量发生变化时(在作用域内定义的所有变量都有一个watch,用于监听变量的状态),触发所有变量的循环检查(从根作用rootscope开始向内检查,即按锚的深度检查,每一次独立的循环检查为一次digest cycle),当检查到数据变更时,则同步数据(如果model中的数据发生变更,则向view同步,如果view中的数据发生变更,则向model同步),直到所有数据稳定。当所有数据稳定后,还会执行一次额外的全量检查。


接下来我们构造一个无限循环的场景来看一下脏检查是如何实现的,顺便看看当发生无限循环时,脏检查是如何处理的。构造两个对象以及对应的监听,对象1的监听器功能为:监听到对象1变更时,则修改对象2,对象2的监听器功能为:监听到对象2变更时,则修改对象1。


在c2.js中定义对象及监听:

/**
 * Created by 李庆 on 2016/10/6.
 */
define(["jquery","../../../framework/service/httpService"],function($,httpService){
    var c2Controller = ["$scope","maskService",function($scope,maskService){
        $scope.test = function(){
            console.log("enter controller");
        };

        $scope.getData = function(){
            maskService.show("get data");
            $.ajax({
                "type":"GET",
                "contentType":"application/json;charset=UTF-8",
                //修改前为"url":"mock/test.json",
                "url":httpService.getUrl("GET","/nova/test.json"),
                "success":function(data){
                    console.log(JSON.stringify(data));
                    setTimeout(function(){
                        maskService.hide();
                    },6000);
                },
                "error":function(data){
                    console.log("error");
                }
            });
        }

        $scope.user1 = 0;
        $scope.user2 = 0;
        $scope.$watch(function() {
            return $scope.user1;
        }, function(oldResult, newResult) {
            console.log("watch1 "+JSON.stringify($scope.user1));
            console.log(JSON.stringify($scope.user2));
            $scope.user2++;
        });

        $scope.$watch(function() {
            return $scope.user2;
        }, function(oldResult, newResult) {
            console.log("watch2 "+JSON.stringify($scope.user1));
            console.log(JSON.stringify($scope.user2));
            $scope.user1++;
        });

    }];
    return c2Controller;
});


变更部分内容如下:



在c2.html中显示对象信息:

<div>
    <input type="button" value="test Controller" ng-click="test()">
    <button ng-click="getData()">request</button>
    <div>{{user1}}</div>
    <div>{{user2}}</div>
</div>


变更部分内容如下:



然后来看一下页面的情况,user1和user2的值都是22:



那么,为什么值会是22呢?再看一下控制台信息(由于无限循环的原因,digest cycle理论上会一直执行下去,变量的值会一直递增,下图的控制台打印信息也可以看到前10次的digest cycle都正常执行):



然而从第11次digest cycle开始时,angularjs认为我们的代码一定发生了问题,终止了脏检查:



也就是说脏检查的digest cycle循环次数是有上限的,也就是10次,第11次则会抛出异常(虽然值还是变更了)。


如本章开头所说,当所有数据稳定后,还会执行一次额外的全量检查,所以,第二轮的digest cycle又开始了(即使前一次digest cycle循环终止的原因是达到了循环次数上限):



从第11次digest cycle开始时(即变量的值从21变更为22时),angularjs又终止了脏检查:



每一次独立的digest cycle都会从外向内检查所有变量并同步,当前一次的digest cycle触发了其他数据的变更,则会触发第二轮的digest cycle,直到第十一轮的digest cycle,达到digest cycle的循环上限,digest cycle循环终止。从这里可以看出,脏检查实际上是非常消耗资源的,在实际的项目开发过程中,需要尽量避免定义数据的多级联动,避免影响页面的可靠性和用户体验。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值