Angularjs-Dirty Checking

Angularjs实现了数据双向绑定,就像下面这样:

<!doctype html>
<htnl ng-app>
<head>
    <script src="js/angular.js"></script>
</head>
<body>
    <input type="text" ng-model="name">
    <h2>Hello {{name}}</h2>
</body>
</html>

这使得在View和Model在变化的时候,都会更新对方:

Angularjs是通过DirtyChecking实现的Two-Way Data Binding:

$scope.$apply:当控制器或指令在Angularjs运行时,Angularjs内部会运行$scope.$apply函数,这个函数会接收一个函数参数并且运行它,在这之后才会在rootScope上运行$digest.

$digest函数将会在$rootScope中被$scope.$apply所调用。它将会在$rootScope中运行digest循环,然后向下遍历每一个作用域并在每个作用域上运行循环。在简单的情形中,digest循环将会触发所有位于$$watchers变量中的所有watchExp函数,将它们和最新的值进行对比,如果值不相同,就会触发监听器。

当digest循环运行时,它将会遍历所有的监听器然后再次循环,只要这次循环发现了”脏值”,循环就会继续下去。如果watchExp的值和最新的值不相同,那么这次循环就会被认为发现了脏值。理想情况下它会运行一次,如果它运行超10次,会看到一个错误。

因此当$scope.$apply运行的时候,$digest也会运行,它将会循环遍历$$watchers,只要发现watchExp和最新的值不相等,变化触发事件监听器。 在AngularJS中,只要一个模型的值可能发生变化,$scope.$apply就会运行。这就是为什么当你在AngularJS之外更新$scope时,例如在一个setTimeout函数中,你需要手动去运行$scope.$apply():这能够让AngularJS意识到它的作用域发生了变化。

$scope.$watch:为了监视一个变量的变化,可以使用$scope.$watch函数。这个函数有三个参数,它指明了”要观察什么”(watchExp),”在变化时要发生什么”(listener),以及要监视的是一个变量还是一个对象。当在检查一个参数时,可以忽略第三个参数。$watch的第一个参数可以是字符串,也可以是函数。

$$watchers:$scope中的$$watchers变量保存着所定义的所有的监视器。如果在控制台中打印$$watchers,会发现它是一个对象数组。$watch函数将会返回一个deregisterWatch函数。这意味着如果使用$scope.$watch对一个变量进行监视,也可以在以后通过调用某个函数来停止监视。

简化版的Dirty-Checking:

HTML:

<input type="text" />

<a href="#" onclick="updateScopeValue();">Set input value to Bob</a>

Javascript:

var Scope = function( ) {
    this.$$watchers = [];
};

Scope.prototype.$watch = function( watchExp, listener ) {
    this.$$watchers.push( {
        watchExp: watchExp,
        listener: listener || function() {}
    } );
};

Scope.prototype.$digest = function( ) {
    var dirty;

    do {
            dirty = false;

            for( var i = 0; i < this.$$watchers.length; i++ ) {
                var newValue = this.$$watchers[i].watchExp(),
                    oldValue = this.$$watchers[i].last;

                if( oldValue !== newValue ) {
                    this.$$watchers[i].listener(newValue, oldValue);

                    dirty = true;

                    this.$$watchers[i].last = newValue;
                }
            }
    } while(dirty);
};

var $scope = new Scope();

$scope.name = ‘Ryan‘;

var element = document.querySelectorAll(‘input‘);

element[0].onkeyup = function() {
    $scope.name = element[0].value;

    $scope.$digest();
};

$scope.$watch(function(){
    return $scope.name;
}, function( newValue, oldValue ) {
    console.log(‘Input value updated - it is now ‘ + newValue);

    element[0].value = $scope.name;
} );

var updateScopeValue = function updateScopeValue( ) {
    $scope.name = ‘Bob‘;
    $scope.$digest();
};

使用上面的代码,无论何时改变了input的值,$scope中的name属性都会相应的发生变化。这样就实现了数据双向绑定。

参考:http://ryanclark.me/how-angularjs-implements-dirty-checking/

时间: 2024-10-14 11:00:39

Angularjs-Dirty Checking的相关文章

angularjs学习总结 详细教程(转载)

1 前言 前端技术的发展是如此之快,各种优秀技术.优秀框架的出现简直让人目不暇接,紧跟时代潮流,学习掌握新知识自然是不敢怠慢. AngularJS是google在维护,其在国外已经十分火热,可是国内的使用情况却有不小的差距,参考文献/网络文章也很匮乏.这里便将我学习AngularJS写成文档,一方面作为自己学习路程上的记录,另一方面也给有兴趣的同学一些参考. 首先我自己也是一名学习者,会以学习者的角度来整理我的行文思路,这里可能只是些探索,有理解或是技术上的错误还请大家指出:其次我特别喜欢编写小

[AngularJS] ngModelController render function

ModelValue and ViewValue: $viewValue: Actual string value in the view. $modelValue: The value in the model that the control is bound to. In Anuglar, it watchs the $modelValue for you and update $viewValue. As you need to tell Angular when you set $vi

深究angularJS系列 - 第二弹

深究angularJS系列 - 第二弹,在初步了解了Angular的基础上,进一步的针对Angular的控制器和作用域问题深入探究O(∩_∩)O~~ Angular控制器 控制器(Controller)的理解 控制器是对view的抽象,用来接收view的事件,响应view的请求: 控制器包含view的静态属性和动态的方法: 控制器与view是一对一的关系. 控制器(Controller)的结构 1 .controller("控制器的名字",function($scoppe){ 2 ..

AngularJS 的数据绑定

单向绑定(ng-bind) 和 双向绑定(ng-model) 的区别 ng-bind 单向数据绑定($scope -> view),用于数据显示,简写形式是 {{}}. 1 <span ng-bind="val"></span> 两者的区别在于页面没有加载完毕 {{val}} 会直接显示到页面,直到 Angular 渲染该绑定数据(这种行为有可能将 {{val}} 让用户看到):而 ng-bind 则是在 Angular 渲染完毕后将数据显示. ng-mo

AngularJs最佳实践二----数据绑定

在我们传统的web框架中,如Rails,Controller混合了来自model的数据并且糅合在模板里成为一个view呈现给用户.这种混合风格会导致single-way-view.视图只能反映在视图呈现的时候的model数据.当然也有写框架有望实现视图和模型的自动数据绑定. AngularJs 采用了一种不同方式,即不是将数据混入模板然后替换Dom元素.AngularJs创建live模板作为视图.视图的独立组件被动态内插值替换,这个特征可能是AngularJs最重要的一个使得我们不用写一行Jav

AngularJS学习总结

在8月份一个项目机会下,决定真正完整地学习使用AngularJS 1.3,下面是我一些总结. PS:有些人很抵触AngularJS这种框架,认为它是在办坏事,装高调,我是认为任何能广泛传播的框架存在不是没有原因,总会有它适用的场景,真正使用了才能发觉东西好坏. 什么是AngularJS 首先AngularJS是一个框架,框架与函数库的区别就在于,框架决定整个项目的开发套路,以框架为主导,函数库却是以项目本身为主导,例如jquery.它就是个双向数据绑定的前端JS框架,双向数据绑定是相比较于其他框

AngularJs学习笔记--Scope

原版地址:http://code.angularjs.org/1.0.2/docs/guide/scope 一.什么是Scope? scope(http://code.angularjs.org/1.0.2/docs/api/ng.$rootScope.Scope)是一个指向应用model的object.它也是expression(http://www.cnblogs.com/lcllao/archive/2012/09/16/2687162.html)的执行上下文.scope被放置于一个类似应

AngularJS数据绑定中数据监控的机制说明

from : http://docs.angularjs.org/guide/scope When the browser calls into JavaScript the code executes outside the Angular execution context, which means that Angular is unaware of model modifications. To properly process model modifications the execu

【转】Build Your own Simplified AngularJS in 200 Lines of JavaScript

原文:http://blog.mgechev.com/2015/03/09/build-learn-your-own-light-lightweight-angularjs/ Build Your own Simplified AngularJS in 200 Lines of JavaScript Edit My practice proved that there are two good/easy ways to learn a new technology: Re-implement i

ExtJS和AngularJS比较

原文地址:http://www.techferry.com/articles/ExtJS-vs-AngularJS.html ExtJS 和AngularJS 是两种企业级的富 UI设计框架. 这篇文章从优势.架构.测试.性能等各个方面比较了 ExtJS 和 AngularJS 我们用ExtJS和AngularJS开发了一个简单测试的应用程序,进行完整的性能测试.我们选取了同样的组件,规范了测试的流程,以保证测试的结果. ExtJS 对比 AngularJS: 特性比较 性能比较 框架比较 架构