Angular12 点击一次搜索按钮返回数据不展示,需点击两次才生效
问题原因
接口请求为异步操作,返回响应赋值数据时,未进入Angular的自动变更检测周期,导致第一次赋值后视图没有同步更新,第二次点击按钮时Angular触发常规变更检测,才把上一次的赋值结果渲染到模板。
解决方案
方案1:手动触发变更检测(最通用,适合绝大多数场景)
在组件中注入ChangeDetectorRef,数据赋值完成后手动标记组件需要更新:
- 导入依赖
import { ChangeDetectorRef } from '@angular/core';
- 构造函数注入
constructor( // 保留原有其他注入逻辑 private cdr: ChangeDetectorRef ) {}
- 修改searchData方法,赋值后触发变更检测
searchData(text:any){ this.service.searchCustomer(text.value).subscribe( response =>{ this.list = response; console.log(this.list); this.cData = this.list.data.model; // 新增此行 this.cdr.markForCheck(); } ); }
方案2:使用async管道(使用OnPush变更检测策略时推荐)
不需要手动处理订阅,由Angular自动管理订阅和变更检测:
- 组件中定义Observable类型变量
import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; // 组件类中定义变量 cData$: Observable<any>;
- 修改searchData方法,直接返回Observable
searchData(text:any){ this.cData$ = this.service.searchCustomer(text.value).pipe( map(response => response.data.model) ); }
- 模板中使用async管道绑定
<!-- 原有绑定写法替换为如下形式,示例为列表循环 --> <div *ngFor="let item of cData$ | async"> {{ item.对应字段名 }} </div>
方案3:强制纳入NgZone管理
如果你的请求服务没有使用Angular自带的HttpClient,而是用了第三方请求库,可将赋值逻辑包裹在NgZone中:
- 导入依赖
import { NgZone } from '@angular/core';
- 构造函数注入
constructor( // 保留原有其他注入逻辑 private zone: NgZone ) {}
- 修改searchData方法
searchData(text:any){ this.service.searchCustomer(text.value).subscribe( response =>{ this.zone.run(() => { this.list = response; this.cData = this.list.data.model; }) } ); }
内容的提问来源于stack exchange,提问作者Parvez Ahmed
相关产品推荐
相关产品推荐

