Angular 2 Cordova App 中的变更检测和区域不同

Angular 2 Change Detection and Zone are Different in Cordova App

我们正在使用 Cordova 和 Angular 2 构建应用程序。我有以下代码:

    import { Component, OnInit, ChangeDetectorRef, NgZone } from '@angular/core';
    import { Location } from '@angular/common';

    declare var WL : any;

    @Component({
      selector: 'app-store',
      templateUrl: './store.component.html',
      styleUrls: ['./store.component.css']
    })

    export class StoreComponent implements OnInit {
      status: string;
      document: any;

      constructor(private _location: Location,  private changeDetector: ChangeDetectorRef,
        private zone: NgZone) { }

      ngOnInit() {
        var collectionName = 'people';
        this.status = "JSONStore is not yet initialized!";
        if(typeof WL !== "undefined" && typeof WL.JSONStore.get(collectionName) !== "undefined")
                this.status = "JSONStore is initialized!";
        }
      }
      jsonStoreInit(){
                var that = this;
                var collectionName = 'people';

                // Object that defines all the collections.
                var collections = {

                    // Object that defines the 'people' collection.
                    people : {

                        // Object that defines the Search Fields for the 'people' collection.
                        searchFields : {name: 'string', age: 'integer'}
                    }
                };

                // Optional options object.
                var options = { };

                /* // Optional username, default 'jsonstore'.
                username : 'carlos',

                // Optional password, default no password.
                password : '123',

                // Optional local key generation flag, default false.
                localKeyGen : false
                };*/

                WL.JSONStore.init(collections, options).then(function () {

                    // Data to add, you probably want to get
                    // this data from a network call (e.g. MobileFirst Adapter).
                    var data = [{name: 'carlos', age: 10}];

                    // Optional options for add.
                    var addOptions = {

                        // Mark data as dirty (true = yes, false = no), default true.
                        markDirty: true
                    };

                    // Get an accessor to the people collection and add data.
                    return WL.JSONStore.get(collectionName).add(data, addOptions);
                })

                .then(function (numberOfDocumentsAdded) {
                    that.status = "JSONStore is initialized!";
                })

                .fail(function (errorObject) {
                // Handle failure for any of the previous JSONStore operations (init, add).
                    alert("Error");
                    console.log(errorObject);
                });
            }
    }

在网络浏览器上,效果很好。当 jsonStoreInit() 触发时,它设置 status 并将 UI 更新为 "JSONStore is initialized"。在 Cordova 应用程序上,如果我不使用手动更改检测,它不会更新 UI。例如,请参见下面我有 //如果这里不存在,它将不会在 CORDOVA 中更新:

       ngOnInit() {
            var collectionName = 'people';
            this.status = "JSONStore is not yet initialized!";
            if(typeof WL !== "undefined" && typeof WL.JSONStore.get(collectionName) !== "undefined")
                this.status = "JSONStore is initialized!";

                //IF THIS ISN'T HERE, IT WILL NOT UPDATE IN CORDOVA
                this.changeDetector.markForCheck();
                this.zone.run(()=> function(){});
            }
       }

       jsonStoreInit(){
            var that = this;
            var collectionName = 'people';

            // Object that defines all the collections.
            var collections = {

                // Object that defines the 'people' collection.
                people : {

                    // Object that defines the Search Fields for the 'people' collection.
                    searchFields : {name: 'string', age: 'integer'}
                }
            };

            // Optional options object.
            var options = { };

            /* // Optional username, default 'jsonstore'.
            username : 'carlos',

            // Optional password, default no password.
            password : '123',

            // Optional local key generation flag, default false.
            localKeyGen : false
            };*/

            WL.JSONStore.init(collections, options).then(function () {

                // Data to add, you probably want to get
                // this data from a network call (e.g. MobileFirst Adapter).
                var data = [{name: 'carlos', age: 10}];

                // Optional options for add.
                var addOptions = {

                    // Mark data as dirty (true = yes, false = no), default true.
                    markDirty: true
                };

                // Get an accessor to the people collection and add data.
                return WL.JSONStore.get(collectionName).add(data, addOptions);
            })

            .then(function (numberOfDocumentsAdded) {
                that.status = "JSONStore is initialized!"

                //IF THIS ISN'T HERE, IT WILL NOT UPDATE IN CORDOVA
                this.changeDetector.markForCheck();
                this.zone.run(()=> function(){});
            })

            .fail(function (errorObject) {
            // Handle failure for any of the previous JSONStore operations (init, add).
                alert("Error");
                console.log(errorObject);
            });
        }

我在简单的按钮点击设置变量时也看到了这一点。除非我手动使用变更检测,否则 Cordova 不会发生任何事情。我只是在学习 Angular 2,所以非常感谢任何对我做错的帮助。

zone.js 修补 XHR 对象和其他 API,如 setIntervaladdEventListener、Promise,以便 angular 在发生某些事情时收到通知并触发变更检测本身。

看起来 JSONStore 正在使用不同的 Promise 实现(jQuery?)zone.js 没有修补它,因此您必须手动触发更改检测或将回调包装在zone.run.