浅谈AngularJs 双向绑定原理(数据绑定机制)

那么什么是双向绑定,下面简单进行讲解。

首先我们要理解数据绑定。我们看到的网站页面中,是由数据和设计两部分组合而成。将设计转换成浏览器能理解的语言,便是html和css主要做的工作。而将数据显示在页面上,并且有一定的交互效果(比如点击等用户操作及对应的页面反应)则是js主要完成的工作。很多时候我们不可能每次更新数据便刷新页面(get请求),而是通过向后端请求相关数据,并通过无刷新加载的方式进行更新页面(post请求)。那么数据进行更新后,页面上相应的位置也能自动做出对应的修改,便是数据绑定。

在以前的开发模式中,这一步一般通过jq操作DOM结构,从而进行更新页面。但这样带来的是大量的代码和大量的操作。如果能在开始的时候,便已经确定好从后端获取的数据到页面上需要进行的操作,当数据发生改变,页面的相关内容也自动发生变化,这样便能极大地方便前端工程师的开发。在新的框架中(angualr,react,vue等),通过对数据的监视,发现变化便根据已经写好的规则进行修改页面,便实现了数据绑定。可以看出,数据绑定是M(model,数据)通过VM(model-view,数据与页面之间的变换规则)向V(view)的一个修改。

而双向绑定则是增加了一条反向的路。在用户操作页面(比如在Input中输入值)的时候,数据能及时发生变化,并且根据数据的变化,页面的另一处也做出对应的修改。有一个常见的例子就是淘宝中的购物车,在商品数量发生变化的时候,商品价格也能及时变化。这样便实现了V——M——VM——V的一个双向绑定。

AngularJs 为 scope 模型上设置了一个 监听队列,用来监听数据变化并更新 view 。每次绑定一个东西到 view(html) 上时 AngularJs 就会往 $watch 队列里插入一条 $watch,用来检测它监视的 model 里是否有变化的东西。当浏览器接收到可以被 angular context 处理的事件时,$digest 循环就会触发。$digest 会遍历所有的 $watch。从而更新DOM。

$watch

这有点类似于我们的观察者模式,在当前作用域$scope下,我们创建一个监控器$watchers和一个监听器$watch,$watchers 负责管理所有的 $watch,当我们每次绑定到UI上的时候就<font color=red>自动</font>创建一个$watch,并把它放到 $watchers。

controller.js

app.controller('MainCtrl', function($scope) {
 $scope.Hello = "Hello";
 $scope.world = "World";
});

index.html

<div>{{Hello}}</div>

这里,即便我们在$scope上添加了两个变量,<font color=red>但是只有一个绑定在了UI上,因此在这里只生成了一个$watch</font>

$digest

当浏览器接收到可以被angular context处理的事件时,$digest循环就会触发。$digest将会遍历我们的$watch,如果$watch没有变化,这个循环检测就将停止,如果有至少一个更新过,这个循环就会再次触发,直到所有的$watch都没有变化。这样就能够保证每个model都已经不会再变化。这就是脏检查(Dirty Checking)机制

controller.js

app.controller('MainCtrl', function() {
 $scope.name = "Foo";

 $scope.changeFoo = function() {
  $scope.name = "Bar";
 }
});

index.js

<div>{{ name }}</div>
<button ng-click="changeFoo()">Change the name</button>
  1. 当我们按下按钮
  2. 浏览器接收到一个事件,进入angular context。
  3. $digest循环开始执行,查询每个$watch是否变化。
  4. 由于监视$scope.name的$watch报告了变化,它会强制再执行一次$digest循环。
  5. 新的$digest循环没有检测到变化。
  6. 更新与$scope.name新值相应部分的DOM。

$apply

$apply 我们可以直接理解为刷新UI。<font color=red>如果当事件触发时,你调用$apply,它会进入angular context,如果没有调用就不会进入,之后的$digest检测机制就不会触发</font>

app.directive('clickable', function() {
 return {
  restrict: "E",
  scope: {
  foo: '='
  },
  template: '<ul style="background-color: lightblue"><li>{{foo}}</li></ul>',
  link: function(scope, element, attrs) {
  element.bind('click', function() {
   scope.foo++;
   console.log(scope.foo);
  });
  }
 }
});

当我们调用clickable指令的时候,我们可以看到foo的值增加了,但是界面上显示的内容并没有改变。$digest脏检测机制没有触发,检测foo的$watch就没有执行。

$apply()方法的两种形式

1) 无参

$scope.$apply();
element.bind('click', function() {
 scope.foo++;
 //if error
 scope.$apply();
});

当我们使用这种形式的时候,如果在scope.$apply之前程序发生异常,那scope.$apply没有执行,界面就不会更新

2) 有参

$scope.$apply(function(){
 ...
})
element.bind('click', function() {
 scope.$apply(function() {
  scope.foo++;
 });
})

如果用这种形式,即使后面的发生异常,数据还是会更新。

在 AngularJS 中使用 $watch

常用的使用方式:

$scope.name = 'Hello';
$scope.$watch('name', function(newValue, oldValue) {
 if (newValue === oldValue) { return; }
 $scope.updated++;
});

传入到$watch()中的第二个参数是一个回调函数,该函数在name的值发生变化的时候会被调用。

如果要监听的是一个对象,那还需要第三个参数:

$scope.data.name = 'Hello';
$scope.$watch('data', function(newValue, oldValue) {
 if (newValue === oldValue) { return; }
 $scope.updated++;
}, true);

表示比较的是对象的值而不是引用,如果不加第三个参数true,在 data.name 变化时,不会触发相应操作,因为引用的是同一引用。

总结

1) 只有在$scope变量绑定到页面上,才会创建 $watch

2) $apply决定事件是否可以进入angular context

3) $digest 循环检查model时最少两次,最多10次(多于10次抛出异常,防止无限检查)

4) AngularJs自带的指令已经实现了$apply,所以不需要我们额外的编写

5) 在自定义指令时,建议使用带function参数的$apply

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 深入学习AngularJS中数据的双向绑定机制

    Angular JS (Angular.JS) 是一组用来开发Web页面的框架.模板以及数据绑定和丰富UI组件.它支持整个开发进程,提供web应用的架构,无需进行手工DOM操作. AngularJS很小,只有60K,兼容主流浏览器,与 jQuery 配合良好.双向数据绑定可能是AngularJS最酷最实用的特性,将MVC的原理展现地淋漓尽致. AngularJS的工作原理是:HTML模板将会被浏览器解析到DOM中, DOM结构成为AngularJS编译器的输入.AngularJS将会遍历DOM模

  • AngularJS入门教程之双向绑定详解

    在这一步你会增加一个让用户控制手机列表显示顺序的特性.动态排序可以这样实现,添加一个新的模型属性,把它和迭代器集成起来,然后让数据绑定完成剩下的事情. 请重置工作目录: git checkout -f step-4 你应该发现除了搜索框之外,你的应用多了一个下来菜单,它可以允许控制电话排列的顺序. 步骤3和步骤4之间最重要的不同在下面列出.你可以在GitHub里看到完整的差别. 模板 app/index.html Search: <input ng-model="query"&g

  • angular双向绑定模拟探索

    前言 本次探索的demo是基于jquery写的,毕竟jquery提供了强大的选择器,用惯了就离不开它了!angular的双向绑定实在是有点精深,本次探索只实现了文本的双向绑定. View-Model 先看效果:文本框输入内容,model层数据也同步过来了 Model-View 先看效果:js改变model层数据,视图也立即随之变化 上我的demo <!DOCTYPE html> <html lang="en" data-swq-app = 'app'> <

  • Angular2实现自定义双向绑定属性

    整理文档,搜刮出一个Angular 2实现自定义 双向绑定 属性的代码,稍微整理精简一下做下分享. import { Component, OnInit, Output, Input, EventEmitter } from '@angular/core'; @Component({ selector: 'twoway', template: ` <input [(ngModel)]="username"> <p>Hello {{username}}!</

  • AngularJS学习笔记(三)数据双向绑定的简单实例

    双向绑定 双向绑定是AngularJS最实用的功能,它节省了大量的代码,使我们专注于数据和视图,不用浪费大量的代码在Dom监听.数据同步上,关于双向更新,可看下图: 数据-->视图 这里我们只演示有了数据以后,如何绑定到视图上. <!DOCTYPE html> <html ng-app="App"> <head> <script type="text/javascript" src="http://sandb

  • Angular JS数据的双向绑定详解及实例

    Angular JS数据的双向绑定 接触AngularJS许了,时常问自己一些问题,如果是我实现它,会在哪些方面选择跟它相同的道路,哪些方面不同.为此,记录了一些思考,给自己回顾,也供他人参考. 初步大致有以下几个方面: 数据双向绑定 视图模型的继承关系 模块和依赖注入的设计 待定 数据的双向绑定 Angular实现了双向绑定机制.所谓的双向绑定,无非是从界面的操作能实时反映到数据,数据的变更能实时展现到界面. 一个最简单的示例就是这样: <div ng-controller="Count

  • 理解Angular数据双向绑定

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

  • 浅谈AngularJs 双向绑定原理(数据绑定机制)

    那么什么是双向绑定,下面简单进行讲解. 首先我们要理解数据绑定.我们看到的网站页面中,是由数据和设计两部分组合而成.将设计转换成浏览器能理解的语言,便是html和css主要做的工作.而将数据显示在页面上,并且有一定的交互效果(比如点击等用户操作及对应的页面反应)则是js主要完成的工作.很多时候我们不可能每次更新数据便刷新页面(get请求),而是通过向后端请求相关数据,并通过无刷新加载的方式进行更新页面(post请求).那么数据进行更新后,页面上相应的位置也能自动做出对应的修改,便是数据绑定. 在

  • 浅谈mvvm-simple双向绑定简单实现

    mvvm模式解放DOM枷锁 mvvm原理分析 JavaScript在浏览器中操作HTML经历了几个不同阶段 第一阶段 直接用浏览器提供的原生API操作DOM元素 var dom = document.getElementById('id'); dom.innerHTML = 'hello mvvm'; 第二阶段 jQuery的出现解决了原生API的复杂性和浏览器间的兼容性等问题,提供了更加简易方便的API $('#id').text('hello mvvm') 第三阶段 MVC模式使前端可以和后

  • 浅谈jQuery事件绑定原理

    jq里面有一个data的方法,给dom元素绑定相关的数据的.当给dom用jq的方法绑定了事件,会生成对应的时间列表 可以看下面的例子(请在firefox中查看 因为firefox中对象支持toSource()) 复制代码 代码如下: <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312"

  • 浅谈React双向数据绑定原理

    目录 什么是双向数据绑定 实现双向数据绑定 数据影响视图 视图影响数据 如果已经学过Vue,并且深入了解过Vue的双向数据绑定的话,就会明白 Vue 2.0 双向数据绑定的核心其实是通过Object.defineProperty来实现数据劫持和监听. 在 Vue 3.0 中则通过 Proxy来实现对整体对象的监听,对 Vue2.0 的优化. 什么是双向数据绑定 数据模型和视图之间的双向绑定. 当数据发生变化的时候,视图也就发生变化,当视图发生变化的时候,数据也会跟着同步变化:可以这样说用户在视图

  • AngularJS双向绑定和依赖反转实例详解

    AngularJS双向绑定和依赖反转 一.双向绑定: UI<-->数据 数据->UI (数据改变UI跟着变) UI->数据 (UI改变数据跟着变) 数据改变->UI改变原理: 监听数据是否改变,如果改变更新UI数据. UI改变->数据改变原理: <html> <body> <input type="text" name="name" value="" id="text1&

  • 浅谈AngularJS中ng-class的使用方法

    有三种方法: 1.通过$scope绑定(不推荐) 2.通过对象数组绑定 3.通过key/value键值对绑定 实现方法: 1.通过$scope绑定(不推荐): function ctrl($scope) { $scope.className = "selected"; } <div class="{{className}}"></div> 2.通过对象数组绑定: function ctrl($scope) { $scope.isSelecte

  • 详解vue的双向绑定原理及实现

    前言 使用vue也好有一段时间了,虽然对其双向绑定原理也有了解个大概,但也没好好探究下其原理实现,所以这次特意花了几晚时间查阅资料和阅读相关源码,自己也实现一个简单版vue的双向绑定版本,先上个成果图来吸引各位: 代码: 效果图: 是不是看起来跟vue的使用方式差不多?接下来就来从原理到实现,从简到难一步一步来实现这个SelfVue.由于本文只是为了学习和分享,所以只是简单实现下原理,并没有考虑太多情况和设计,如果大家有什么建议,欢迎提出来. 本文主要介绍两大内容: 1. vue数据双向绑定的原

  • Vue 的双向绑定原理与用法揭秘

    本文实例讲述了Vue 的双向绑定原理与用法.分享给大家供大家参考,具体如下: Vue 中需要输入什么内容的时候,自然会想到使用 <input v-model="xxx" /> 的方式来实现双向绑定.下面是一个最简单的示例 <div id="app"> <h2>What's your name:</h2> <input v-model="name" /> <div>Hello

  • 浅谈Servlet的Cookie和Session机制

    一.Servlet Cookies Cookies定义:Cookies是存储在客户端计算机上的文本文件,并保留了用户的各种跟踪信息. Cookies作用:会话保持,如完成用户的登录与状态保持 Cookies的工作原理: 客户端向服务区发起登录请求 服务器脚本(代码)向浏览器发送一组Cookies,例如:姓名,年龄等 浏览器将这些信息存储在本地计算机上,以备将来使用 当下一次浏览器向web服务器发送任何请求时.浏览器会把这些Cookies信息发送到服务器,服务器将使用这些信息来识别账户 1.1 C

  • 浅谈Spring Session工作原理

    目录 1.引入背景 2.使用方法 3.工作流程 4.缓存机制 5.事件订阅 6.总结 1.引入背景 HTTP协议本身是无状态的,为了保存会话信息,浏览器Cookie通过SessionID标识会话请求,服务器以SessionID为key来存储会话信息.在单实例应用中,可以考虑应用进程自身存储,随着应用体量的增长,需要横向扩容,多实例session共享问题随之而来. 应用部署在Tomcat时,session是由Tomcat内存维护,如果应用部署多个实例,session就不能共享.Spring Ses

随机推荐