Angular 5 + Ionic 3移动端Http Post请求后数据绑定失效问题
问题原因分析
你遇到的这个情况很典型,主要有两个核心原因:
- 移动端的
mouse:up事件其实是浏览器模拟出来的,它并没有运行在Angular的NgZone上下文里,所以当你在回调里更新变量后,Angular根本不知道数据发生了变化,自然不会触发视图更新——直到你点击屏幕触发了其他能触发变更检测的事件,视图才会同步。 - 如果你的canvas用的是第三方库(比如fabric.js),它的事件回调本身就跑在Angular的变更检测机制之外,不管是桌面还是移动端,都可能出现这种“数据更新了但视图不更”的情况。
解决方案
下面给你三个递进的解决思路,按需选择:
方案一:用NgZone把回调拉回Angular上下文
这是最稳妥的方式,把mouse:up回调里的逻辑包裹在NgZone.run()里,强制让代码运行在Angular的变更检测范围内。
// 先导入NgZone import { NgZone } from '@angular/core'; // 在组件构造函数里注入NgZone constructor(private zone: NgZone) {} ionViewDidLoad() { this.canvas.on('mouse:up', (o) => { if (this.isAutoDraw) { // 把所有涉及数据更新的代码包裹在zone.run里 this.zone.run(() => { const image = this.canvas.toDataURL("image/png"); this.autoDrawService.postImage(image).subscribe(response => { // 这里更新你的绑定变量 this.yourBindingVariable = response; }); }); } }); }
方案二:手动触发变更检测
如果不想用NgZone,也可以直接注入ChangeDetectorRef,在数据更新后手动通知Angular去检测变化并更新视图。
// 导入ChangeDetectorRef import { ChangeDetectorRef } from '@angular/core'; // 组件构造函数注入 constructor(private cdr: ChangeDetectorRef) {} ionViewDidLoad() { this.canvas.on('mouse:up', (o) => { if (this.isAutoDraw) { const image = this.canvas.toDataURL("image/png"); this.autoDrawService.postImage(image).subscribe(response => { this.yourBindingVariable = response; // 手动触发变更检测 this.cdr.detectChanges(); }); } }); }
方案三:改用原生触摸事件(更适配移动端)
既然是在移动端测试,不如直接抛弃模拟的mouse:up,改用原生的触摸事件。如果你的canvas库支持触摸事件(比如fabric.js就有touch:end事件),直接监听触摸结束事件,这样事件本身就在Angular的变更检测范围内,不需要额外处理。
ionViewDidLoad() { // 替换成触摸结束事件 this.canvas.on('touch:end', (o) => { if (this.isAutoDraw) { const image = this.canvas.toDataURL("image/png"); this.autoDrawService.postImage(image).subscribe(response => { this.yourBindingVariable = response; }); } }); }
总结
优先推荐方案三,因为它更贴合移动端的原生行为;如果因为业务原因必须用mouse:up,方案一和方案二都能解决问题,其中方案一的通用性更强,适合大部分第三方库事件的场景。
内容的提问来源于stack exchange,提问作者Devan Madlani
相关产品推荐
相关产品推荐

