typescript – Angular 2 – 为什么我需要zone.run()?
发布时间:2020-12-17 07:53:14 所属栏目:安全 来源:网络整理
导读:我正在尝试在Angular 2中创建一个显示服务数据的组件.该服务基本上从用户的一些输入后从json文件加载一些数据.我一直试图让组件更新,但它似乎没有识别更改,除非我从我的服务提交事件后调用zone.run().组件的代码如下: @Component({ selector: 'assess-asset
我正在尝试在Angular 2中创建一个显示服务数据的组件.该服务基本上从用户的一些输入后从json文件加载一些数据.我一直试图让组件更新,但它似乎没有识别更改,除非我从我的服务提交事件后调用zone.run().组件的代码如下:
@Component({ selector: 'assess-asset-group',directives: [AssetComponent,AssetHeaderComponent,NgFor,NgIf],template: ` <div *ngIf="assetService.schema != null"> <div class="asset-group" *ngFor="#assetTypeName of assetService.schema.assetTypeNames"> <div class="asset-type-title"><span>{{assetService.schema.assetTypes[assetTypeName].name}}s</span></div> <table class="asset-group-table" cellpadding=0 cellspacing=0> <thead> <tr assess-asset-header [assetType]="assetService.schema.assetTypes[assetTypeName]"></tr> </thead> <tbody> <tr assess-asset *ngFor="#asset of assetService.assetsForType(assetTypeName)" [asset]="asset"></tr> </tbody> </table> <button class="new-asset-btn" (click)="assetService.addAsset(assetTypeName)">New</button> </div> </div>`,providers: [provide(AssetService,{useValue: injector.get(AssetService)})] }) export class AssetGroupComponent { public assetService: AssetService; public zone: NgZone; constructor( @Inject(AssetService) assetService: AssetService,zone: NgZone) { this.assetService = assetService; this.zone = zone; } ngOnInit() { this.assetService.proejectLoadedEmitter.subscribe((e) => { this.zone.run(() => { }) }); } ngOnDestroy() { this.assetService.proejectLoadedEmitter.unsubscribe(); } } 我做错了什么,或者这是我需要做什么才能更新视图? UPDATE – AssetService类 @Injectable() export class AssetService{ public assets: Assets.Asset[] = []; public assetTypeDefinitions: any = null; public schema: Schema = null; public assetsAsObj: any = null; // Asset file loaded as object @Output() proejectLoadedEmitter: EventEmitter<any> = new EventEmitter(); constructor(){ } public loadProject(config: Project){ // Load schema // populate AssetTypeDefinitions as object keyed by type let data = fs.readFileSync(config.schemaPath,'utf8'); if (!data) { utils.logError("Error reading schema file"); return; } let struc = fs.readFileSync(config.structurePath,'utf8'); if (!struc) { utils.logError("Error reading structure file"); return; } this.schema = new Schema(JSON.parse(data),struc); this.readAssets(config.assetFilePath); } /** * @brief Adds a new asset to the assets array * @details Constructs the asset based on the type and populates * its fields with appropreiate default values * * @param type The type of the asset - specified in the schema */ public addAsset(type: string): void { // Need to make sure there is a loaded type definition for the specified type if(!this.schema.assetTypes.hasOwnProperty(type)){ utils.logError("Error occured during call to addAsset - type "" + type + "" is not specified in the loaded schema"); return; } // Creeate a new asset object - passing in the type definition from the schema this.assets.push(new Assets.Asset(this.schema.assetTypes[type])); } /** * Write the current assets to a file using the specified format * If the outputPasth isn't specied try and load it from the project.json file */ public writeAssets(format:AssetWriteFormat,outputPath?: string) : void { var outStructureStr = this.schema.structureStr; // insert AS properties from schema into output assets this.schema.properties.forEach(prop => { outStructureStr = outStructureStr.replace(new RegExp('"' + prop +'"','i'),this.retriveValueForSchemaProperty(prop)); }); fs.writeFileSync("C:/Projects/Assess/assets.json",outStructureStr); } public readAssets(inputPath?: string) : void{ let assetsStr = fs.readFileSync(inputPath,'utf8'); let strucToAssetMap = {}; let strucObj = JSON.parse(this.schema.structureStr); this.schema.properties.forEach(p => { strucToAssetMap[p] = this.findValueInObject(strucObj,p).reverse(); }); // @TODO Load custom properties let assetsObj = JSON.parse(assetsStr); var c = null; strucToAssetMap["AS_ASSETS"].forEach(p => { if(c == null){ c = assetsObj[p]; }else{ c = c[p]; } }); c.forEach((asset) => { let a:Assets.Asset = new Assets.Asset(this.schema.assetTypes[asset.type],asset); this.assets.push(a); }); console.log(this.assets); this.proejectLoadedEmitter.emit(null); } public assetsForType(type:string): Assets.Asset[]{ var ret: Assets.Asset[] = []; for(let idx in this.assets){ if(this.assets[idx].definition.type === type){ ret.push(this.assets[idx]); } } return ret; } public retriveValueForSchemaProperty(property: string) : string{ if(AS_SchemaTypes.indexOf(property) != -1){ switch (property) { case "AS_ASSETS": let outAssets = []; this.assets.forEach((asset) => { let outAsset = {}; outAsset["type"] = asset.definition.type; for (let key in asset.fields) { outAsset[key] = asset.fields[key].value; } outAssets.push(outAsset); }); return JSON.stringify(outAssets,null,"t"); } }else{ // @TODO Retrive custom properties return '"DDDDDD"'; } return ""; } public findValueInObject(obj: any,property: string,path: any[] = []): any[] { for(let x in obj){; let val = obj[x]; if (val == property){ path.push(x); return path; } else if(val != null && typeof val == 'object'){ let v = this.findValueInObject(val,property,path); if(v != null){ path.push(x); return path; } } } return null; } }
这需要了解您正在使用的AssetService的内部工作方式.
Angular在其区域中运行组件的代码,其中大多数异步API(addEventListener,setTimeout,…)都被修补,因此区域可以在发生此类异步回调时通知Angular.这是Angular运行变化检测的时候. 如果您通过其他方式在Angular或AssetService之外初始化AssetService执行Angulars区域之外的代码,则Angular不会收到有关发生异步回调的通知,也不会运行更改检测. 使用zone.run(…),您可以明确地在Angulars区域内执行代码,然后运行更改检测. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
相关内容
- bash – find,xargs:为每个文件执行命令链
- 禁用在Vim R插件中插入“< - ”的下划线“_”快捷方式[复制
- angularjs – Movilizer – 使用具有离子的MovilizerJS
- jaxws-webservice编程续
- 使用方法GET的Angular HttpClient参数不起作用
- macos – 使用终端命令备份到外部HDD
- Angular 2单击ngClass,如何仅应用于SELF而不是ALLF中的所有
- bootstrap-如何在modal中使用collapse
- 具有使用AngularJS并连接到ASP.NET Web API 2的登录屏幕的S
- Webservice设计和模式