【问题标题】:Ionic 2 - Changes to Model are not updated in the view / UIIonic 2 - 对模型的更改未在视图/UI 中更新
【发布时间】:2017-01-24 23:06:26
【问题描述】:

我很难理解如何在不触发 UI 事件的情况下将组件内属性的更改传播到实际视图。如果我来回走动,用户界面就会更新。

这是我的组件,它每秒检索一次 BLE 通知。每次通知后,都需要在视图中更新通知的结果值。我可以看到通知显示在开发人员控制台中。

import { Component, ChangeDetectionStrategy, ChangeDetectorRef, Input, Output} from '@angular/core';
import { NavController, NavParams } from 'ionic-angular';
import { BLE } from 'ionic-native';
import {Observable} from 'rxjs/Observable';


@Component({
templateUrl: 'build/pages/devices/devices.html',
//changeDetection: ChangeDetectionStrategy.OnPush
})

export class DevicePage {

private nav:NavController = null;
private navParams:NavParams = null;
private device:any;
private connecting:any;
private characteristics:any;
private data:any;
private temp:any;


static get parameters() {
  return [[NavParams],[NavController]];
}
//
constructor(navParams, nav, private cd:ChangeDetectorRef ) {
  this.nav = nav;
  this.navParams = navParams;
  this.device = this.navParams.get('device');
  this.connect(this.device.id);
}

connect(device) {
/*
  var service = "6e524635-312d-444b-2020-202020202020";
  var characteristic_read = "6e524635-312d-444b-2062-7574746f6e20";
  var characteristic_write = "6e400002-b5a3-f393-e0a9-e50e24dcca9e"
*/
  var bleUART = "6e400001-b5a3-f393-e0a9-e50e24dcca9e";
  var RXD = "6e400003-b5a3-f393-e0a9-e50e24dcca9e";
  var TXD = "6e400002-b5a3-f393-e0a9-e50e24dcca9e";
  //this.hello = "Hello";
  BLE.connect(device).subscribe(
    peripheralData => {
      console.log("Connect:" + JSON.stringify(peripheralData));
        BLE.startNotification(device, bleUART, RXD).subscribe(
          buffer => {this.temp = String.fromCharCode.apply(null, new Uint8Array(buffer));
          //  this.cd.markForCheck();
              this.cd.detectChanges();
            console.log("Data: " + this.temp);
            },
          error => {console.log("Error Notification" + JSON.stringify(error));
      })},
      error => {console.log("Error Connecting" + JSON.stringify(error));})
  }
}

对应的HTML:

<ion-header>
<ion-navbar>
  <ion-title>
    Hotplate Status
  </ion-title>
</ion-navbar>
</ion-header>

<ion-content>
  <h2>Connected Device:</h2>
  <p>{{device.name}}</p>
  <h1>Temperature:</h1>
  <p>{{temp}}</p>

</ion-content>

添加了根页面以显示调用 connect() 的位置

import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
import { DevicePage } from '../devices/devices';
import { BLE } from 'ionic-native';

@Component({templateUrl: 'build/pages/home/home.html'})

export class HomePage {
  private nav:NavController = null; // please add this line as default generated page plus the --ts option on command line.
  private devices:any;
  private isScanning:any;

  static get parameters() {
    return [[NavController]];
  }

  constructor(nav:NavController) {
    this.nav = nav;
    this.devices = [];
    this.isScanning = false;
  }

  startScanning() {
    console.log('Scanning Started');
    this.devices = [];
    this.isScanning = true;
    BLE.startScan([]).subscribe(device => {
    this.devices.push(device);
    });

    setTimeout(() => {
    BLE.stopScan().then(() => {
      console.log('Scanning has stopped');
      console.log(JSON.stringify(this.devices))
      this.isScanning = false;
    });
    }, 5000);
  }

  connectToDevice(device) {
    console.log('Connect To Device');
    console.log(JSON.stringify(device))
    this.nav.push(DevicePage, {
    device: device
  });
}
}

和相应的HTML:

<ion-navbar *navbar>
  <ion-title>
    Devices
  </ion-title>
  <ion-buttons end>
   <button (click) = "startScanning()">Scan</button>
  </ion-buttons>
</ion-navbar>

<ion-content>
  <ion-list insert>
    <ion-item-sliding *ngFor="#device of devices" #slidingItem>
      <button ion-item (click)="connectToDevice(device)">
        <h2>{{device.name}}</h2>
        <p>{{device.id}}</p>
        <p>{{device.rssi}}</p>
      </button>
    </ion-item-sliding>
  </ion-list>
  <ion-spinner *ngIf="isScanning==true" name="circles"></ion-spinner>
</ion-content>

我尝试过更改检测,但 markForCheck()results 出现异常。当我直接使用 NgZone 时,会显示类似的 TypeError。

Uncaught TypeError: Cannot read property 'markForCheck' of undefined(anonymous function) @ app.bundle.js:84SafeSubscriber.__tryOrUnsub @ app.bundle.js:94435SafeSubscriber.next @ app.bundle.js:94384Subscriber._next @ app.bundle.js:94334Subscriber.next @ app.bundle.js:94298cordova.callbackFromNative @ cordova.js:293processMessage @ cordova.js:1081processMessages @ cordova.js:1104pollOnce @ cordova.js:973pollOnceFromOnlineEvent @ cordova.js:960

我正在使用最新的 Ionic2 Beta。 知道我在这里做错了什么吗?

谢谢, 延斯

【问题讨论】:

  • 您是仅从构造函数(显示在您的代码中)还是从其他地方调用connect()
  • 不,connect() 仅从构造函数中调用。我已经编辑了最初的帖子并添加了 javascript 和 html。

标签: javascript angular bluetooth-lowenergy ionic2


【解决方案1】:

您需要在参数中添加ChangeDetectorRef

 return [[NavParams],[NavController],[ChangeDetectorRef]];

【讨论】:

  • 好的,太棒了!此外,我不得不将 this.cd.markForCheck() 更改为 this.cd.detectChanges() 但现在每次通知后都会更新 UI。非常感谢!
  • 是的!这篇文章是 4 小时彩虹结束时的金罐。首先,它引导我找到“ChangeDetector”,我不知道它存在,它似乎是 Angular 2 的“$scope.$apply()”版本——其次给了我一个如何实现的好例子。谢谢各位!终于像魅力一样工作了。
猜你喜欢
  • 2017-09-07
  • 1970-01-01
  • 2016-08-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-30
相关资源
最近更新 更多