NativeScript Angular中Firebase数据变更后视图不更新问题排查
问题:NativeScript Angular + Firebase聊天应用中,他人发送消息时视图不更新
我正在用NativeScript结合Angular与Firebase插件开发聊天应用,通过Firebase的addValueEventListener监听指定路径的数据变更,代码如下:
firebase.addValueEventListener( (result) => { for(var key in result.value){ this.posts.push(result.value[key].Message); } this.messages = this.posts; // 用this.messages更新视图 this.posts=[]; }, '/forum/messages');
遇到的问题:自己发送消息时视图能正常更新,但他人发送消息时,messages数组已经变更,视图却没有更新,必须重启应用才能看到新消息,请问这是什么原因?
原因分析与解决方案
这个问题的核心是Angular的变更检测机制没有被触发。
当你自己发送消息时,操作通常是在Angular的上下文(比如按钮点击事件、表单提交等)中执行的,这些操作会自动触发Angular的变更检测,所以视图能实时更新。但Firebase的addValueEventListener回调是运行在Angular的NgZone(Angular的执行上下文)之外的异步操作,当回调里更新messages数组时,Angular根本不知道数据发生了变化,自然不会去更新视图。
这里有两种常用的解决方法:
方法一:使用NgZone将回调包裹起来
你可以注入NgZone服务,把Firebase回调里的代码放到zone.run()方法中,这样就能让代码回到Angular的执行上下文,自动触发变更检测:
import { NgZone } from "@angular/core"; // 在组件构造函数中注入NgZone constructor(private zone: NgZone) {} // 修改监听代码 firebase.addValueEventListener( (result) => { this.zone.run(() => { for(var key in result.value){ this.posts.push(result.value[key].Message); } this.messages = this.posts; this.posts=[]; }); }, '/forum/messages');
方法二:手动触发变更检测
另一种方式是注入ChangeDetectorRef服务,在更新数据后手动调用detectChanges()方法来通知Angular更新视图:
import { ChangeDetectorRef } from "@angular/core"; // 在组件构造函数中注入ChangeDetectorRef constructor(private cdr: ChangeDetectorRef) {} // 修改监听代码 firebase.addValueEventListener( (result) => { for(var key in result.value){ this.posts.push(result.value[key].Message); } this.messages = this.posts; this.posts=[]; // 手动触发变更检测 this.cdr.detectChanges(); }, '/forum/messages');
另外还有个小建议:你当前的代码每次触发监听都会把所有消息重新push一遍,可能会导致重复消息。可以考虑对比现有消息的key,只添加新的消息,这样体验会更好。
内容的提问来源于stack exchange,提问作者Stel Dare
相关产品推荐
相关产品推荐

