最近做公司新项目用的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. 分享一个开源的网盘下载工具BaiduPCS-Go

    大家在使用网盘的时候,一定忍受不了限速下载的速度.今天给大家分享一个开源的网盘下载项目BaiduPCS-Go.Go语言编写,仿 Linux shell 文件处理命令的百度网盘命令行客户端.多平台支持, ...

  2. python flask中的代码约定

    在Python社区中有许多关于代码风格的约定.如果你写过一段时间Python了,那么也许对此已经有些了解. 我会简单介绍一下,同时给你一些URL链接,从中你可以找到关于这个话题的详细信息. 让我们提出 ...

  3. Beta 冲刺day3

    1.昨天的困难,今天解决的进度,以及明天要做的事情 昨天的困难:昨天主要是对第三方与企业复杂的逻辑关系进行分析和优化,以及进行部分模块的功能测试和代码测试. 今天解决的进度:根据前天得到的需求问题进行 ...

  4. ArcCore重构-目标文件结构化

    基于官方arc-stable-9c57d86f66be,AUTOSAR版本3.1.5   基本问题 3. 编译系统中所有代码文件通过搜索路径(VPATH)中搜索,存在名称污染问题,需加入路径信息:   ...

  5. [ Java面试题 ]基础篇之二

    1.String s = new String("xyz");创建了几个StringObject?是否可以继承String类? 两个或一个都有可能,"xyz"对 ...

  6. ScalaPB(4): 通用跨系统protobuf数据,sbt设置

    我们知道,在集群环境节点之间进行交换的数据必须经过序列化/反序列化处理过程,而在这方面protobuf是一个比较高效.易用的模式.用户首先在.proto文件中用IDL来定义系统中各种需要进行交换的数据 ...

  7. CSS定位使用方法

    .box0 { width: 200px; height: 200px; position: relative; background: #cfa } .box0-1,.box0-2 { width: ...

  8. 纯干货!耗时1个月整理黑马程序员Java教程+笔记+配套工具

    学习Java是不是很苦?找不到资料?不了解学习步骤?想要全面的线路图! 或者是找资料,前面免费,后面收费?工具软件要收费? 当当当~~今天就没有这个状态发生了!不信就证明给你看 1.学习路线图 2.J ...

  9. 如何高效的编写与同步博客 (.NET Core 小工具实现)

    一.前言 写博客,可以带给我们很多好处,比如可以让我们结识更多志同道合的人:在写博客过程中去查技术资料或者实践可以让我们对知识的掌握和理解更加深刻:通过博客分享能帮助他人收获分享的快乐等等.写博客真的 ...

  10. C/C++ 数据结构之算法

    数据结构中的排序算法. 排序算法的相关知识: (1)排序的概念:所谓排序就是要整理文件中的记录,使之按关键字递增(或递减)次序排列起来. (2)稳定的排序方法:在待排序的文件中,若存在多个关键字相同的 ...