Angular之双向数据绑定

---恢复内容开始---

angular最初进入前端开发人员视野的时候,给人以不可磨灭的印象之一就是它的双向数据绑定的实现。本篇章会先介绍如何使用此功能,然后在深入解释它的双向绑定的机制是如何实现的。

angular中的data-binding指的是模型models和视图views之间的自动同步。angular实现双向绑定后,会让你觉得数据模型是页面中数据唯一的真实来源。当model改变后,视图反映改变,反之亦然。通俗的说,所谓的双向数据绑定,无非就是从界面的操作能实时反映到数据,数据的变更能实时展现到界面。据各最简单的例子:

<div ng-controller="CounterCtrl">
    <span ng-bind="counter"></span>
    <button ng-click="counter++">increase</button>
</div>
function CounterCtrl($scope) {
    $scope.counter = 1;
}

上面的例子很简单,每当点击一次按钮,界面上的数据就加1。

但是,新手很可能会碰到下面这样的问题。

var app = angular.module("test", []);

app.directive("myclick", function() {
    return function (scope, element, attr) {
        element.on("click", function() {
            scope.counter++;
        });
    };
});

app.controller("CounterCtrl", function($scope) {
    $scope.counter = 0;
});

<body ng-app="test">
    <div ng-controller="CounterCtrl">
        <button myclick>increase</button>
        <span ng-bind="counter"></span>
    </div>
</body>

上面的例子也很简单:想要实现的事:点击按钮时,span元素中counter加1。但是实际上,视图上并不会这样。然而model中counter确实增加了。也就是说,并没有实现angular所说的数据双向绑定。测试请访问:http://plnkr.co/edit/?p=preview

但是如果在scope.counter++;后面加上scope.$digest();后又没问题了,而第一个例子中并没有使用$digest函数,如果使用了反而报错。这是怎么回事?下面使用原生javascript看看事怎么实现的。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>two-way binding</title>
    </head>
    <body onload="init()">
        <button ng-click="inc">
            increase 1
        </button>
        <button ng-click="inc2">
            increase 2
        </button>
        <span style="color:red" ng-bind="counter"></span>
        <span style="color:blue" ng-bind="counter"></span>
        <span style="color:green" ng-bind="counter"></span>

        <script type="text/javascript">
            /* 数据模型区开始 */
            var counter = 0;

            function inc() {
                counter++;
            }

            function inc2() {
                counter+=2;
            }
            /* 数据模型区结束 */

            /* 绑定关系区开始 */
            function init() {
                bind();
            }

            function bind() {
                var list = document.querySelectorAll("[ng-click]");
                for (var i=0; i<list.length; i++) {
                    list[i].onclick = (function(index) {
                        return function() {
                            window[list[index].getAttribute("ng-click")]();
                            apply();
                        };
                    })(i);
                }
            }

            function apply() {
                var list = document.querySelectorAll("[ng-bind=‘counter‘]");
                for (var i=0; i<list.length; i++) {
                    list[i].innerHTML = counter;
                }
            }
            /* 绑定关系区结束 */
        </script>
    </body>
</html>

上面没有直接使用DOM的onclick方法,而是搞了一个ng-click,然后在bind里面把这个ng-click对应的函数拿出来,绑定到onclick的事件处理函数中。为什么要这样呢?因为数据虽然变更了,但是还没有往界面上填充,我们需要在此做一些附加操作,即添加apply()方法。而由于angular使用的是脏检测,也就是说,需要自己做一些事情来触发脏检测,在应用到这个数据对应的DOM元素上。所以前面一段代码只是监听了click,而不是‘ng-click’,即并没有触发脏检查,不会更新到视图上面。

在一些基于setter的框架中,它可以 在给数据设置的时候,对DOM元素上绑定的变量重新设值。但是脏检查的机制并没有这个阶段,它没有任何途径在数据变更之后,立即得到通知,所以只能在每个事件入口调用apply(),把数据模型的改变反映到视图上。在真正的angular中,一般都是先对模型数据进行脏检查,确实改变了,才对视图设值。

那么,为什么在ng-click里面调用$digest的话,会报错呢(就是第一段代码)?因为Angular的设计,同一时间只允许一个$digest运行,而ng-click这种内置指令已经触发了$digest,当前的还没有走完,所以就出错了。

上面的问题归结为:怎么触发脏检查?什么时候触发?那就不得不提到scope下面的三个重要方法:$digest,$apply,$watch.下篇详细介绍这三个函数。

最后,在强调一下:angular对Dom常用的操作,xhr时间进行了封装,在里面写了触发digest()方法的流程。脏检查只有在指令事件触发后,才会进入$digest()内,如DOM事件(比如在input中输入文本,点击按钮等等),XHR响应事件($http),浏览器location变更事件($location),Time事件( $timeout,$interval)。

时间: 2024-07-31 22:23:19

Angular之双向数据绑定的相关文章

Angular之双向数据绑定(下)

本篇详细介绍:1.angular时如何通过脏检查来实现对$scope对象上变量的双向绑定的.2.实现angular双向绑定的三个重要方法:$digest(),$apply(),$watch(). angular不像Ember.js,通过动态设置setter函数和getter函数来实现双向绑定,脏检查允许angular监听可能存在可能不存在的变量. $scope.$watch语法糖:$scope.$watch(watchExp,Listener,objectEquality); 监听一个变量何时变

Angular JS - 3 - Angular JS 双向数据绑定

一 .数据绑定 1. 数据绑定: 数据从一个地方A转移(传递)到另一个地方B, 而且这个操作由框架来完成2. 双向数据绑定: 数据可以从View(视图层)流向Model(模型,也就是数据), 也可以从Model流向View 视图(View): 也就是我们的页面(主要是Andular指令和表达式) 模型(Model) : 作用域对象(当前为$rootScope), 它可以包含一些属性或方法 当改变View中的数据, Model对象的对应属性也会随之改变: ng-model指令 数据从View==>

angular的双向数据绑定

方向1:模型数据(model) 绑定 到视图(view) 实现方法1:{{model变量名}} $scope.num=10 <p>{{num}}</p> 实现方法2: 常用指令(ngRepeat.ngIf.ngShow/Hide/Src....) $scope.list=[{name:'sam',age:22},{name:'tom',age:37},{name:'kim',age:28}] <tr ng-repeat='std in list'> <td>

angular.js双向数据绑定实现动画特效

一.HTML 1.引入必要的js文件,这个不多说了(注意由于之后要使用angular提供的动画效果和路由效果,所以要引入angular-animate.js和angular-route.js两个文件) 2.body内加入以下代码:  <div class="page {{pageClass}}" ng-view></div> ng-view不多说,class通过双向绑定的方式,通过controller动态控制class中的{{pageclass}} 另外不要忘了

angular和vue双向数据绑定

angular和vue双向数据绑定的原理(重点是vue的双向绑定) 我在整理javascript高级程序设计的笔记的时候看到面向对象设计那章,讲到对象属性分为数据属性和访问器属性,我们平时用的js对象90%以上都只是用到数据属性;我们向来讲解下数据属性和访问器属性到底是什么? 数据属性:数据属性包含一个数据值的位置,在这个位置可以读取和写入值. 访问器属性:访问器属性不包含数据值;他们包含一对getter和setter函数在读取访问器属性时,会调用getter函数,这个函数负责返回有效的值,在写

vue和angular双向数据绑定原理

都是视图和数据的双向传递: angular双向数据绑定原理: 就是通过脏值检测的方式判断数据是否有变更: 当数据中的值改变的化,就会到$degiest(是vue内部的方法)中循环查找,当值不改变了,就会把数据显示到视图中: vue双向数据绑定原理: 数据劫持,使用ES5的Object.definpropoty() 方法监控的数据,数据的读取使用的是setter和getter,用于视图和数据的同步绑定:

Angular 1.63 双向数据绑定 通过 $http 发送数据

html 部分 <body ng-app="app"> <form action="" method="">账号 <div ng-controller="login"> <label for=""><input type="text" ng-model="data.name" name="name&quo

Angular数据双向绑定

Angular数据双向绑定 AngularJS诞生于2009年,由Misko Hevery 等人创建,后为Google所收购.是一款优秀的前端JS框架,已经被用于Google的多款产品当中.AngularJS有着诸多特性,最为核心的是:MVVM.模块化.自动化双向数据绑定.语义化标签.依赖注入等等. 一.什么是数据双向绑定 Angular实现了双向绑定机制.所谓的双向绑定,无非是从界面的操作能实时反映到数据,数据的变更能实时展现到界面. 一个最简单的示例就是这样: <div ng-control

双向数据绑定和单项数据绑定的认识

参考文章: https://segmentfault.com/q/1010000002511449/a-1020000002514653 https://www.zhihu.com/question/49964363/answer/136022879 单向数据绑定:指的是我们先把模板写好,然后把模板和数据(数据可能来自后台)整合到一起形成HTML代码,然后把这段HTML代码插入到文档流里面. 单向数据绑定缺点:HTML代码一旦生成完以后,就没有办法再变了,如果有新的数据来了,那就必须把之前的HT