最近做公司新项目用的angular7,中碰到了一个很头疼的问题在绑定对象中的数据改变时,页面视图没有跟新,需点击页面中的时间元素后才会更新。以前使用angularJs也经常碰到类似情况,这种时候一般的方式使使用脏检查(Dirty checking)让angularJs检查绑定到视图上的数据来实现对页面数据的刷新。

  接触angular7时间还不久,angular高版本中提供了一系列组件的生命周期钩子,能在组件生命周期的各个阶段,对组件进行操作,监测组件中输入数据的变化,基本少很少碰到需要用到类似于angularJs中脏检查的情况。一直以为在高版本中的angular中已经不会出现需要脏检查的情况了,可是该来的迟早会来。

  在项目中由于使用了公司的自己的播放插件,angular自身的事件注册机制无效,只能使用原生的js位视频播放插件注册点击事件。实现点击插件后通过插件绑定的回调函数将该分屏信息发送给父组件,在父组件中通过对父组件绑定对象中的属性值的改变来改变父组件的样式。 

  

// 插件中的代码片段
ngAfterViewInit() {
// 页面视图初始化完成之后为视频播放插件添加点击事件
this.videoObj = document.getElementById('obj' + this.screen.id);
this.videoObj.addEventListener('click', () => {
this.selectThisScreen(this.screen);
}, false);
} private selectThisScreen(screen) {
// 输出该分屏对象,输出给父组件
this.screenSelected.emit(screen);
} // 父组件中的代码片段
private selectedScreen(screen) {
this.videoLayoutService.selectedScreen(screen, this.videoLayoutOutput);
} // videoLayoutService 片段
this.screensConfig.screens.map(item => {
if (item.id === screen.id) {
item.selected = !item.selected; // 这是想要更新的值!!
if (item.selected) {
videoLayoutOutput.emit({
device: {
id: screen.device.Id,
code: screen.device.SerialNo,
selectedCamera: screen.device.SelectedCamera
}
});
} else {
videoLayoutOutput.emit({ device: { id: null, code: null, selectedCamera: null } });
}
} else if (item.id !== screen.id) {
item.selected = false;
}
});

  可是由于插件事件绑定只支持原生js的方式,没有有使用angular自身的事件绑定机制(已测试,在不适用该插件的条件下,使用angular自身的事件绑定机制view层能够监测到数据的跟新),view层没能监测到绑定数据的变化。在尝试了各种方式,和各种生命周期钩子后(甚至测试了ngDoCheck)都没有效果后都没能达到想要的效果,这时我想会不会现在angular7中也存在和angularJs中数据更新视图没更新的一样问题,如果是那也应该有类似与$scope.$applay()这样类似的方式来解决这个问题。

  然后去查了一下官网文档,在文档中没有直接找到类似方法。后去网上找,后来在篇文章中发现了NgZone这个服务(具体哪一篇忘记记录了,找的博客太多了后来忘记了),然后去官网查了查用法。

  官网文档中使这样描述的:An injectable service for executing work inside or outside of the Angular zone.(用于在Angular区域内外执行工作的可注入服务。)看的云里雾里。。然后又看下面的说明。

  The most common use of this service is to optimize performance when starting a work consisting of one or more asynchronous tasks that don't require UI updates or error handling to be handled by Angular. Such tasks can be kicked off via runOutsideAngular and if needed, these tasks can reenter the Angular zone via run.

  大概是说这个服务最常见的用途是在启动一个或多个异步组成工作是优化性能时使用,这些任务不由angular处理UI更新或错误处理(感动终于找到问题所在了!因为插件使用原生js进行事件绑定,没有走angular自身的事件绑定机制导致了angular框架不处理UI更新。。所以需要在这里使用NgZone这个服务),这些任务可以通过runOutsideAngular启动,如果需要,这些任务可以通过run重新进入Angular区域。

  也就是说我现在可以使用NgZone服务的提供的run()方法将这个事件加入到angular的UI更新管理区域中,一切引刃而解。

  在父组件中注册NgZone服务使用run()方法

// 父组件中的代码片段
constructor(private videoLayoutService: VideoLayoutService, private zone: NgZone) {
}

private selectedScreen(screen) {
  this.zone.run(() => {
   this.videoLayoutService.selectedScreen(screen, this.videoLayoutOutput);
  });
}

  最后来简单说明下NgZone中的几个方法的使用

  run():在Angular区域内同步执行fn函数,并返回函数返回的值。通过run运行函数允许您从在Angular区域之外执行的任务(通常通过runOutsideAngular启动)重新进入Angular区域。在这个函数中调度的任何未来任务或微任务都将在Angular区域中继续执行。如果发生同步错误,它将被重新抛出,而不是通过onError报告。

  runTask():以任务的形式在Angular区域内同步执行fn函数,并返回函数返回的值。通过run运行函数允许您从在Angular区域之外执行的任务(通常通过runOutsideAngular启动)重新进入Angular区域。在这个函数中调度的任何未来任务或微任务都将在Angular区域中继续执行。如果发生同步错误,它将被重新抛出,而不是通过onError报告。

  runGuarded() :与 run() 相同,除了同步错误是通过onError捕获和转发的,而不是重新抛出。

  runOutsideAngular() : 在Angular的父区同步执行fn函数,并返回函数返回的值。通过runOutsideAngular运行函数可以让您逃离Angular的区域,并做一些不会触发Angular变化检测或受制于Angular错误处理的工作。在这个函数中调度的任何未来任务或微任务都将在Angular区域之外继续执行。使用run重新进入Angular区域并执行更新应用程序模型的工作。

  

 

angular2-7中的变化监测的更多相关文章

  1. Angular开发实践(五):深入解析变化监测

    什么是变化监测 在使用 Angular 进行开发中,我们常用到 Angular 中的绑定--模型到视图的输入绑定.视图到模型的输出绑定以及视图与模型的双向绑定.而这些绑定的值之所以能在视图与模型之间保 ...

  2. 深入理解Angular2变化监测和ngZone

    转载自GitHub JTangming : https://github.com/JTangming/tm/issues/4 Angular应用程序通过组件实例和模板之间进行数据交互,也就是将组件的数 ...

  3. VueX中state变化捕捉不到_getters监测不到state的变化

    原因 可能有多种原因, 现在我说一下我碰到的一种情况: state种有一个变量叫state,它是一个json对象, 可把我害惨了.因为他这个json长这个样: messageBox:{ friendI ...

  4. js 实时监听input中值变化

    注意:用到了jquery需要引入jquery.min.js. 需求: 1.每个地方需要分别打分,总分为100; 2.第一个打分总分为40; 3.第二个打分总分为60. 注意:需要判断null.&quo ...

  5. 第50讲:Scala中Variance变化点

    王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-64讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...

  6. [转] Express 4 中的变化

    http://www.cnblogs.com/haogj/p/3985438.html 概览 从 Express 3 到Express 4 是一个巨大的变化,这意味着现存的 Express 3 应用在 ...

  7. iOS中让Settings Bundle中的变化立即在App中反应出来的两种方法

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 为了能够在Settings Bundle中的变化在进入App后 ...

  8. ITMS-SERVICES://方式安装IPA在IOS 7.1中的变化

    转:https://laoyur.com/?p=414 iOS7.1中,通过itms-services://方式安装ipa已经发生了改变,.plist文件必须是https://的,.ipa文件的链接则 ...

  9. Angular2+URL中的 # 引发的思考

    1.先分析 # 的作用 1.1. # 的涵义 #代表网页中的位置.其右面的字符就是该位置的标识符.比如,http://www.example.com/index.html#print就代表网页inde ...

随机推荐

  1. Effective C++ 读书笔记(46-50)

    条款四十六:需要类型转换时请为模板定义非成员函数 条款四十七:请使用traits classes 表现类型信息 1.整合重载技术后,traits classes 有可能在编译期对类型执行if...el ...

  2. FastDfs上传图片

    1.1. 上传步骤 1.加载配置文件,配置文件中的内容就是tracker服务的地址. 配置文件内容:tracker_server=192.168.25.133:22122 2.创建一个TrackerC ...

  3. 免费Git客户端:sourcetree详细介绍

    一.简介:一个用于Windows和Mac的免费Git客户端.Sourcetree简化了如何与Git存储库进行交互,这样您就可以集中精力编写代码.通过Sourcetree的简单Git GUI可视化和管理 ...

  4. 第七章之S5PV210移植到Nandflash

    1,之前的操作都是基于SD卡进行运行的,如今在Nandfalsh中运行u-boot.因为s5p_goni.h配置文件没有配置Nand相关文件,所以先配置Nand文件. 在include/configs ...

  5. PAT1021:Deepest Root

    1021. Deepest Root (25) 时间限制 1500 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue A graph ...

  6. 并发库应用之十一 & 阻塞队列的应用

    队列包含固定长度的队列和不固定长度的队列,队列的规则就是:先进先出.固定长度的队列往里放数据,如果放满了还要放,阻塞式队列就会等待,直到有数据取出,空出位置后才继续放:非阻塞式队列不能等待就只能报错了 ...

  7. SSM-SpringMVC-21:SpringMVC中处理器方法之返回值Object篇

    ------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 今天要记录的是处理方法,返回值为Object的那种,我给它分了一下类: 1.返回值为Object数值(例如1) ...

  8. Vue.js中前端知识点总结笔记

    1.框架和库的区别: 框架:framework 有着自己的语法特点.都有对应的各个模块库 library 专注于一点 框架的好处: 1.提到代码的质量,开发速度 2.提高代码的复用率 3.降低模块之间 ...

  9. 14.app后端如何设计api

    app和后端的交互,一般都是通过后端提供的api实现.api的设计,估计很多刚进入app后端的小伙伴会一无头绪,不知道怎么入门.下面根据自己3年的app后端经验,总结出下几个api设计原则,给小伙伴参 ...

  10. 通过MSSQL分析器跟踪研究EM内部行为并解决identify列问题

    今天有人问到MSSQL表里的IDENTITY字段,如何让它在复制原来数据到该表时,原来数据的IDENTITY字段不变,而新插入数据时,新插入的数据的IDENTITY依然增长,查了些资料,做了个实验,最 ...