这个问题是上周的,当时觉得这个问题的解决办法太简单了,不用写博客记录,但是潘老师今天今天又遇到了需要使用这个的地方,感觉问题虽然不难,但是,写篇博客,方便自己查询,也给了其他人搜索到解决办法的机会。

问题描述

项目中使用到了ifame,理想状态是:当点击ifame中的按钮时,将会调用通过angular写的一个函数,函数将会修改一个ngif的判断条件,显示一个弹窗,

但现实是:当点击ifame中的按钮时,将会调用通过angular写的一个函数,函数将会修改一个ngif的判断条件,然后就没有然后了.

 

开始的时候自己直接懵了, 方法确实执行了, 但界面没修改, 问了问潘老师, 潘老师说看看生命周期函数是否执行了, 果然, 所有的生命周期函数都没有调用。

解决办法

既然生命周期函数没调用,我们让他调用不就行了,值已经变化了,但是界面不变化,说明,angular 不知道值变化了,所以我们可以让angular 主动进行变更检测,让它知道已经发生了变化。

对此我们可以使用 ChangeDetectorRef

变化监测类 - ChangeDetectorRef

Angular 在整个运行期间都会为每一个组件创建 ChangeDetectorRef 的实例,该实例提供了相关方法来手动管理变化监测。有了这个类,我们自己就可以自定义组件的变化监测策略了,如停止/启用变化监测或者按指定路径变化监测等等。

它有以下方法:

  • markForCheck():把根组件到该组件之间的这条路径标记起来,通知Angular在下次触发变化监测时必须检查这条路径上的组件。
  • detach():从变化监测树中分离变化监测器,该组件的变化监测器将不再执行变化监测,除非再次手动执行reattach()方法。
  • reattach():把分离的变化监测器重新安装上,使得该组件及其子组件都能执行变化监测。
  • detectChanges():手动触发执行该组件到各个子组件的一次变化监测。

所以,我们可以使用 detectChanges() 来达到目标

使用方法

// 在组件中注入
 constructor(private changeDetectorRef: ChangeDetectorRef) {
 }
 
 // 直接使用
 test() {
 this.changeDetectorRef.detectChanges()
 }

angular何时进行变化检测

总结起来, 主要有如下几种情况:

  • 用户输入操作,比如点击,提交等
  • 请求服务端数据(XHR)
  • 定时事件,比如 setTimeoutsetInterval

Angular并不是捕捉对象的变动,它采用的是在适当的时机去检验对象的值是否被改动,这个时机就是这些异步事件的发生。

这个时机是由 Zone.js 去掌控的,它获取到了整个应用的执行上下文,能够对相关的异步事件发生、完成或者异常等进行捕获,然后驱动 Angular 的变化监测机制执行。

Zone.js的作用

实际上 Zone,js 有一个叫猴子补丁的东西。在 Zone.js 运行时,就会为这些异步事件做一层代理包裹,也就是说Zone.js运行后,调用 setTimeout、addEventListener 等浏览器异步事件时,不再是调用原生的方法,而是被猴子补丁包装过后的代理方法。代理里setup了钩子函数, 通过这些钩子函数, 可以方便的进入异步任务执行的上下文

//以下是Zone.js启动时执行逻辑的抽象代码片段
function zoneAwareAddEventListener() {...}
function zoneAwareRemoveEventListener() {...}
function zoneAwarePromise() {...}
function patchTimeout() {...}
window.prototype.addEventListener=zoneAwareAddEventListener;
window.prototype.removeEventListener=zoneAwareRemoveEventListener;
window.prototype.promise = zoneAwarePromise;
window.prototype.setTimeout = patchTimeout;

关于 Zone.js 的详细内容可以看 这篇文章 。

angular变化检测策略

angular 提供了两种变更检测策略,除了上述得Default外还有一种 OnPush 的检测机制

OnPush 与 Default 之间的差别: 当检测到与子组件输入绑定的值没有发生改变时,变化检测就不会深入到子组件中去 。

一个OnPush的例子

app.comonent.ts

@Component({
 selector: 'app-root',
 template: `
 <h1>{{title}}</h1>
 <h2>user.name: {{user.name}}</h2>
 <button type="button" (click)="changeUserName()"> 改变属性
 </button>
 <button type="button" (click)="changeUserObject()">
  改变对象
 </button>
 <app-test [user]="user"></app-test>
 `,
})
export class AppComponent {
 title = 'OnPush Demo';
 user: User = new User({name: 'yunzhi'});

 changeUserName() {
 this.user.name = 'new name';
 }

 changeUserObject() {
 this.user = new User({name: 'new user'});
 }
}

test.component.ts

@Component({
 selector: 'app-test',
 template: `
 <div>
  <h3>test 组件</h3>
  <p>
  <label>User:</label>
  <span>{{user.name}}</span>
  </p>
 </div>`,
 // 使用OnPush模式只需要加上下面这段代码
 changeDetection: ChangeDetectionStrategy.OnPush
})
export class TestComponent implements OnInit {
 @Input() user: User;

 constructor() {
 }

 ngOnInit() {
 }

}

这时当我们点击改变属性按钮时test组件显示的并不会变化,只有改变user得引用test组件显示的才会变化,如下图所示

总结

本来以为这个问题没什么可写的,直接解决好像就完事了,但没想到写着写着感觉能写的越来越多,比如 变更检测的顺序 ,还有 ExpressionChangedAfterItHasBeenCheckedError 都是应该知道的问题,但是感觉这些和主题又没有什么关系,想了想还是算了。

到此这篇关于angula中使用iframe点击后不执行变更检测的问题的文章就介绍到这了,更多相关angula iframe 变更检测内容请搜索Devmax以前的文章或继续浏览下面的相关文章希望大家以后多多支持Devmax!

angula中使用iframe点击后不执行变更检测的问题的更多相关文章

  1. 详解Html5页面实现下载文件(apk、txt等)的三种方式

    这篇文章主要介绍了详解Html5页面实现下载文件(apk、txt等)的三种方式,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  2. 详解使用postMessage解决iframe跨域通信问题

    这篇文章主要介绍了详解使用postMessage解决iframe跨域通信问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  3. 基于HTML十秒做出淘宝页面

    十分钟做出一个网页,看似不可思议,下面小编给大家带来了基于HTML十秒做出淘宝页面,只分为两步,代码超级简单,需要的朋友参考下吧

  4. html5唤起app的方法

    这篇文章主要介绍了html5唤起app的方法的相关资料,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  5. 跨域修改iframe页面内容详解

    这篇文章主要介绍了跨域修改iframe页面内容详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  6. 使用postMessage让 iframe自适应高度的方法示例

    这篇文章主要介绍了使用postMessage让 iframe自适应高度的方法示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  7. ios – Cordova 3.7在每个本机通话中复制iframe

    由于我已升级到Cordova3.7,每个本地调用都将一个新的iframe附加到DOM,如下所示.为了排除我现有的代码影响cordova的可能性,我尝试使用cordovaCLI创建一个新的代码,添加控制台插件,并在设备控制台中的setInterval循环中调用console.log().因此,我在DOM中收到了大量的iframe.我在iPad3,iOS7上尝试过使用xCode6构建应用程序.有没有人遇到这个问题?

  8. swift – 与WKWebView进行JavaScript同步本地通信

    使用WKWebView可以在JavaScript和Swift/Obj-C本机代码之间进行同步通信吗?

  9. android – 如何在webview中使用iframe播放vimeo视频?

    在谷歌研究之后,我写了上面的代码,但没有工作.在这个没有错误发生,但是当我点击播放按钮进度条显示一段时间,然后它消失并再次显示播放按钮…有人可以建议我如何解决这个问题?

  10. html5唤醒APP小记

    这篇文章主要介绍了html5唤醒APP小记的相关资料,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

随机推荐

  1. js中‘!.’是什么意思

  2. Vue如何指定不编译的文件夹和favicon.ico

    这篇文章主要介绍了Vue如何指定不编译的文件夹和favicon.ico,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  3. 基于JavaScript编写一个图片转PDF转换器

    本文为大家介绍了一个简单的 JavaScript 项目,可以将图片转换为 PDF 文件。你可以从本地选择任何一张图片,只需点击一下即可将其转换为 PDF 文件,感兴趣的可以动手尝试一下

  4. jquery点赞功能实现代码 点个赞吧!

    点赞功能很多地方都会出现,如何实现爱心点赞功能,这篇文章主要为大家详细介绍了jquery点赞功能实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  5. AngularJs上传前预览图片的实例代码

    使用AngularJs进行开发,在项目中,经常会遇到上传图片后,需在一旁预览图片内容,怎么实现这样的功能呢?今天小编给大家分享AugularJs上传前预览图片的实现代码,需要的朋友参考下吧

  6. JavaScript面向对象编程入门教程

    这篇文章主要介绍了JavaScript面向对象编程的相关概念,例如类、对象、属性、方法等面向对象的术语,并以实例讲解各种术语的使用,非常好的一篇面向对象入门教程,其它语言也可以参考哦

  7. jQuery中的通配符选择器使用总结

    通配符在控制input标签时相当好用,这里简单进行了jQuery中的通配符选择器使用总结,需要的朋友可以参考下

  8. javascript 动态调整图片尺寸实现代码

    在自己的网站上更新文章时一个比较常见的问题是:文章插图太宽,使整个网页都变形了。如果对每个插图都先进行缩放再插入的话,太麻烦了。

  9. jquery ajaxfileupload异步上传插件

    这篇文章主要为大家详细介绍了jquery ajaxfileupload异步上传插件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. React学习之受控组件与数据共享实例分析

    这篇文章主要介绍了React学习之受控组件与数据共享,结合实例形式分析了React受控组件与组件间数据共享相关原理与使用技巧,需要的朋友可以参考下

返回
顶部