浅谈Angular 的变化检测的方法


Posted in Javascript onMarch 01, 2018

Change Detection (变化检测) 是 Angular 2 中最重要的一个特性。当组件中的数据发生变化的时候,Angular 2 能检测到数据变化并自动刷新视图反映出相应的变化。

在介绍变化检测之前,我们要先介绍一下浏览器中渲染的概念,渲染是将模型映射到视图的过程。模型的值可以是 JavaScript 中的原始数据类型、对象、数组或其他数据对象。然而视图可以是页面中的段落、表单、按钮等其他元素,这些页面元素内部使用 DOM(Document Object Model) 来表示,为了更好地理解,我们来看一个具体的示例:

<h4 id="greeting"></h4> <script> document.getElementById("greeting").innerHTML = "Hello World!"; </script>

这个例子很简单,因为模型不会变化,所以页面只会渲染一次。如果数据模型在运行时会不断变化,那么整个过程将变得复杂。因此为了保证数据与视图的同步,页面将会进行多次渲染。接下来我们来考虑一下以下几个问题:

1、什么时候模型会发生变化

2、模型产生了什么变化

3、变化后需要更新的视图区域在哪里

4、怎么更新对应视图区域

而变化检测的基本目的就是解决上述问题。在 Angular 2 中当组件内的模型发生变化的时候,组件内的变化检测器就会检测到更新,然后通知视图刷新。因此变化检测器有两个主要的任务:

1、检测模型的变化

2、通知视图刷新

接下来我们来分析一下什么是变化,变化是怎么产生的。

变化和事件

变化是旧模型与新模型之间的区别,换句话说变化产生了一个新的模型。让我们来看一下下面的代码:

import { Component } from '@angular/core'; @Component({
 selector: 'exe-counter',
 template: `
 <p>当前值:{{ counter }}</p>
 <button (click)="countUp()"> + </button>` }) export class CounterComponent {
 counter = 0;

 countUp() { this.counter++;
 }
}

页面首次渲染完后,计数器的当前值为0。当我们点击 + 按钮时,计数器的 counter 值将会自动加1,之后页面中当前值也会被更新。在这个例子中,点击事件引起了 counter 属性值的变化。

我们继续看下一个例子:

import { Component, OnInit } from '@angular/core'; @Component({
 selector: 'exe-counter',
 template: `
  <p>当前值:{{ counter }}</p>
 ` }) export class CounterComponent implements OnInit {
 counter = 0;
 ngOnInit() {
  setInterval(() => { this.counter++;
  }, 1000);
 }
}

该组件通过 setInterval 定时器,实现每秒钟 counter 值自动加1。在这种情况下,它是定时器事件引起了属性值的变化。最后我们再来看个例子:

import { Component, OnInit } from '@angular/core'; import { Http } from '@angular/http'; @Component({
 selector: 'exe-counter',
 template: `
  <p>当前值:{{ counter }}</p>
 ` }) export class CounterComponent implements OnInit {
 counter = 0; constructor(private http: Http) {}
 ngOnInit() { this.http.get('/counter-data.json')
    .map(res => res.json())
    .subscribe(data => { this.counter = data.value;
    });
 }
}

该组件在进行初始化的时候,会发送一个 HTTP 请求去获取初始值。当请求成功返回的时候,组件的 counter 属性的值会被更新。在这种情况下,它是由 XHR 回调引起了属性值的变化。

现在我们来总结一下,引起模型变化的三类事件源:

1、Events:click, mouseover, keyup ...

2、Timers:setInterval、setTimeout

3、XHRs:Ajax(GET、POST ...)

这些事件源有一个共同的特性,即它们都是异步操作。那我们可以这样认为,所有的异步操作都有可能会引起模型的变化。

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

Javascript 相关文章推荐
收藏Javascript中常用的55个经典技巧
Aug 12 Javascript
原生js拖拽(第一课 未兼容)拖拽思路
Mar 29 Javascript
jQuery中获取checkbox选中项等操作及注意事项
Nov 24 Javascript
jquery实现仿新浪微博评论滚动效果
Aug 06 Javascript
整理JavaScript创建对象的八种方法
Nov 03 Javascript
学习JavaScript设计模式之观察者模式
Apr 22 Javascript
jQuery插件扩展extend的简单实现原理
Jun 24 Javascript
jQuery如何封装输入框插件
Aug 19 Javascript
JQuery中解决重复动画的方法
Oct 17 Javascript
详解webpack4升级指南以及从webpack3.x迁移
Jun 12 Javascript
vue动态设置页面title的方法实例
Aug 23 Javascript
使用vue-element-admin框架从后端动态获取菜单功能的实现
Apr 29 Vue.js
ES6学习笔记之map、set与数组、对象的对比
Mar 01 #Javascript
Node.js静态服务器的实现方法
Feb 28 #Javascript
JS脚本加载后执行相应回调函数的操作方法
Feb 28 #Javascript
vue+webpack 打包文件 404 页面空白的解决方法
Feb 28 #Javascript
webpack项目调试以及独立打包配置文件的方法
Feb 28 #Javascript
vue-cli+webpack项目 修改项目名称的方法
Feb 28 #Javascript
vue 组件 全局注册和局部注册的实现
Feb 28 #Javascript
You might like
一个php导出oracle库的php代码
2009/04/20 PHP
php数组转换js数组操作及json_encode的用法详解
2013/10/26 PHP
Yii2单元测试用法示例
2016/11/12 PHP
ThinkPHP框架表单验证操作方法
2017/07/19 PHP
php解决crontab定时任务不能写入文件问题的方法分析
2019/09/16 PHP
农历与西历对照
2006/09/06 Javascript
Javascript 学习笔记 错误处理
2009/07/30 Javascript
Javascript 面向对象之重载
2010/05/04 Javascript
深入理解JavaScript 闭包究竟是什么
2013/04/12 Javascript
jquery js 获取时间差、时间格式具体代码
2013/06/05 Javascript
JS滚轮事件onmousewheel使用介绍
2013/11/01 Javascript
js打开windows上的可执行文件示例
2014/05/27 Javascript
jQuery插件jcrop+Fileapi完美实现图片上传+裁剪+预览的代码分享
2015/04/22 Javascript
6种javascript显示当前系统时间代码
2015/12/01 Javascript
javascript实现数组去重的多种方法
2016/03/14 Javascript
webpack中引用jquery的简单实现
2016/06/08 Javascript
基于vue.js实现侧边菜单栏
2017/03/20 Javascript
vue组件学习教程
2017/09/09 Javascript
Mongoose中document与object的区别示例详解
2017/09/18 Javascript
Django与Vue语法的冲突问题完美解决方法
2017/12/14 Javascript
vue项目中jsonp跨域获取qq音乐首页推荐问题
2018/05/30 Javascript
VueJS 组件参数名命名与组件属性转化问题
2018/12/03 Javascript
JS随机密码生成算法
2019/09/23 Javascript
vue输入节流,避免实时请求接口的实例代码
2019/10/30 Javascript
利用Hyperic调用Python实现进程守护
2018/01/02 Python
将Dataframe数据转化为ndarry数据的方法
2018/06/28 Python
python实现RabbitMQ的消息队列的示例代码
2018/11/08 Python
python程序 线程队列queue使用方法解析
2019/09/23 Python
浅谈Django QuerySet对象(模型.objects)的常用方法
2020/03/28 Python
纯CSS3代码实现switch滑动开关按钮效果
2016/08/30 HTML / CSS
Watchshop德国:欧洲在线手表No.1
2019/06/20 全球购物
介绍一下ICMP(Internet Control Message Protocol)Internet控制信息协议
2016/11/26 面试题
介绍一下Mysql的存储引擎
2015/02/12 面试题
销售经理工作职责范文
2013/12/03 职场文书
大学校园生活自我鉴定
2014/01/13 职场文书
《月球之谜》教学反思
2016/02/20 职场文书