angular2-7中的变化监测
最近做公司新项目用的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中的变化监测的更多相关文章
- Angular开发实践(五):深入解析变化监测
什么是变化监测 在使用 Angular 进行开发中,我们常用到 Angular 中的绑定--模型到视图的输入绑定.视图到模型的输出绑定以及视图与模型的双向绑定.而这些绑定的值之所以能在视图与模型之间保 ...
- 深入理解Angular2变化监测和ngZone
转载自GitHub JTangming : https://github.com/JTangming/tm/issues/4 Angular应用程序通过组件实例和模板之间进行数据交互,也就是将组件的数 ...
- VueX中state变化捕捉不到_getters监测不到state的变化
原因 可能有多种原因, 现在我说一下我碰到的一种情况: state种有一个变量叫state,它是一个json对象, 可把我害惨了.因为他这个json长这个样: messageBox:{ friendI ...
- js 实时监听input中值变化
注意:用到了jquery需要引入jquery.min.js. 需求: 1.每个地方需要分别打分,总分为100; 2.第一个打分总分为40; 3.第二个打分总分为60. 注意:需要判断null.&quo ...
- 第50讲:Scala中Variance变化点
王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-64讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...
- [转] Express 4 中的变化
http://www.cnblogs.com/haogj/p/3985438.html 概览 从 Express 3 到Express 4 是一个巨大的变化,这意味着现存的 Express 3 应用在 ...
- iOS中让Settings Bundle中的变化立即在App中反应出来的两种方法
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 为了能够在Settings Bundle中的变化在进入App后 ...
- ITMS-SERVICES://方式安装IPA在IOS 7.1中的变化
转:https://laoyur.com/?p=414 iOS7.1中,通过itms-services://方式安装ipa已经发生了改变,.plist文件必须是https://的,.ipa文件的链接则 ...
- Angular2+URL中的 # 引发的思考
1.先分析 # 的作用 1.1. # 的涵义 #代表网页中的位置.其右面的字符就是该位置的标识符.比如,http://www.example.com/index.html#print就代表网页inde ...
随机推荐
- UML小白入门基础教程
面向对象的问题的处理的关键是建模问题.建模可以把在复杂世界的许多重要的细节给抽象出.许多建模工具封装了UML(也就是Unified Modeling Language™,统一建模语言),这篇课程的目的 ...
- 通过Django Channels设计聊天机器人WEB框架
这两个月都在忙着设计针对银联客服业务的智能聊天机器人,上一周已经交完设计报告,这一周还和部门同事一起分享了系统设计及运行效果.因为时间的关系,系统原型我使用了Flask+jQuery的组合,感觉用以原 ...
- VueJs(11)---vue-router(进阶2)
vue-router(进阶2) 上篇文章讲了第一篇vue-router相关文章,文章地址:VueJs(10)---vue-router(进阶1) 一.命名路由 有时候,通过一个名称来标识一个路由显得更 ...
- git命令行常用几个指令(细节问题)
GIT PUSH/PULL时总需要输入用户名密码的解决方案: git config --global credential.helper store 查看当前的配置信息: git config --s ...
- SpringMVC+GSON 对象序列化--日期格式的处理
Gson异常强大因此使用它代替了Jackson作为SpringMVC消息转换器. 在自己的项目中,发现对象在序列化后,日期格式出现了问题. 先看问题 在员工表中有一列是生日,字段类型为Date,也就是 ...
- Java中的String类型
1.基本类型和引用类型 在C语言里面,是有指针这么一个变量类型的,指针变量保存的就是所要指向内容的地址.在Java里面,没有了指针的这么个说法,而是换了一个词:引用类型变量. 先说Java里面的基本类 ...
- CSS学习笔记六:写原生导航栏
因为刚开始学习CSS时,只了解了一些基本样式,然后就跑去学习bootstrap.bootstrap是个不错的东西,挺好玩,起码让你写界面写的轻轻松松,几行引入代码,再来个复制粘贴就解决了,而且boot ...
- Spring @Conditional注解的使用
Spring Boot的强大之处在于使用了Spring 4框架的新特性:@Conditional注释,此注释使得只有在特定条件满足时才启用一些配置. 下面来介绍如何使用Condition 首先写一个类 ...
- 使用 Java8 Optional 的正确姿势(转)
我们知道 Java 8 增加了一些很有用的 API, 其中一个就是 Optional. 如果对它不稍假探索, 只是轻描淡写的认为它可以优雅的解决 NullPointException 的问题, 于是代 ...
- SSM-MyBatis-14:Mybatis中智能标签
------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 谈论到智能,有什么要想的没有? 我下面放张图 相信都见过这个吧,你在之前没有学习过框架的时候怎么写的,动态sq ...