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 ...
随机推荐
- MVC-AOP(面向切面编程)思想-Filter之IExceptionFilter-异常处理
HandleErrorAttribute MVC中的基本异常分类: Action异常 T view异常 T, service异常 T, 控制器异常 F(异常get不到), ...
- spring-mvc报红错误
can't resolve spring 以及运行测试案例报错 ‘无法找到路径’ 解决办法是在pom文件里面重新配置 对应 resource <resources> <resou ...
- IAAS-libvirt介绍。
Libvirt介绍 Libvirt与hypervisor无关,其提供与多种操作系统虚拟化能力进行交互的API与工具库. Libvirt提供了一个通用稳定的抽象层,可以安全的操作物理机上的虚拟机,同时为 ...
- python2.7 的中文编码处理,解决UnicodeEncodeError: 'ascii' codec can't encode character 问题
最近业务中需要用 Python 写一些脚本.尽管脚本的交互只是命令行 + 日志输出,但是为了让界面友好些,我还是决定用中文输出日志信息. 很快,我就遇到了异常: UnicodeEncodeError: ...
- Quartz学习--二 Hello Quartz! 和源码分析
Quartz学习--二 Hello Quartz! 和源码分析 三. Hello Quartz! 我会跟着 第一章 6.2 的图来 进行同步代码编写 简单入门示例: 创建一个新的java普通工程 ...
- 使用 Swoole 来加速你的 Laravel 应用
Swoole 是为 PHP 开发的生产级异步编程框架. 他是一个纯 C 开发的扩展, 他允许 PHP 开发者在 PHP 中写 高性能,可扩展的并发 TCP, UDP, Unix socket, HTT ...
- Zookeeper学习
http://www.cnblogs.com/caosiyang/archive/2012/11/09/2763190.html http://www.cnblogs.com/haippy/tag ...
- 言简意赅的TIME_WAIT
为什么要有TIME_WAIT? 主动关闭端发送完ACK后等2MSL(最长分节生命期),防止对端没有收到ACK这种情况,重发. 官方点,再官方点...... (1) 可靠地实现TCP全双工连接的终止: ...
- PAT1041: Be Unique
1041. Be Unique (20) 时间限制 100 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue Being uniqu ...
- Linux时间子系统之一:认识timer_list和timer_stats和使用
内核版本:v3.4.xxx 一.前言 内核提供了方便查看当前系统TickDevice.活动的Timer列表以及Timer使用的统计信息. 内核分别用两个节点来表示TimerList和Timer统计信息 ...