简体   繁体   English

如何不使用ngOnInit()在Angular中显示数据?

[英]How to display data in Angular without ngOnInit()?

I have a cigarette counter app in Ionic 4. Stackblitz here: https://stackblitz.com/edit/ionic-8xrdgo . 我在Ionic 4中有一个香烟计数器应用程序。请在此处Stackblitz: https ://stackblitz.com/edit/ionic-8xrdgo。 I need to display the up-to-date consumption data in the history segment when user presses on the Add One button in the counter segment. 当用户按下计数器细分中的“添加一个”按钮时,我需要在历史记录细分中显示最新的消费数据。 For some reason, an app reload is required for the up-to-date data to be displayed in the history segment. 由于某些原因,需要重新加载应用程序才能在历史记录段中显示最新数据。

To reproduce the problem: 重现该问题:

  1. Start the app without consumption in the Storage 在不consumption存储空间的情况下启动应用程序
  2. Click the Add One button. 单击添加一个按钮。 A new consumption is added to storage successfully. 新消耗已成功添加到存储。
  3. Click the Add One button again. 再次单击“添加一个”按钮。 The existing consumption should be updated now, but for some reason it is not. 现在应该更新现有的消耗量,但是由于某种原因没有更新。 Also, the history segment does not display the data. 此外,历史记录段不会显示数据。
  4. Reload the app. 重新加载应用程序。
  5. Click the Add One button. 单击添加一个按钮。 Now the existing consumption is successfully updated to the storage and the consumption is displayed in the history segment. 现在,现有消耗量已成功更新到存储中,并且消耗量显示在历史记录段中。

The problem here is that reloading the app is necessary in order to update the existing consumption to the storage and display it. 这里的问题是,必须重新加载应用程序才能将现有消耗量更新到存储中并显示出来。

Full code here: 完整代码在这里:

home.page.html: home.page.html:

<ion-header>
  <ion-toolbar>
    <ion-segment [(ngModel)]="segment" color="dark">
      <ion-segment-button value="info">
        Info
      </ion-segment-button>
      <ion-segment-button value="counter">
        Counter
      </ion-segment-button>
      <ion-segment-button value="history">
        History
      </ion-segment-button>
    </ion-segment>
  </ion-toolbar>
</ion-header>

<ion-content padding>

  <div *ngIf="segment == 'info'">
    <h1 class="center">Cigarette pack info</h1>
    <ion-item>
      <ion-input placeholder="Price" type="number" [(ngModel)]="pack.price"></ion-input>
    </ion-item>
    <ion-item>
      <ion-input placeholder="Cigarette count" type="number" [(ngModel)]="pack.cigarettecount"></ion-input>
    </ion-item>
    <br>
    <ion-button expand="block" color="dark" (click)="savePack()">Save</ion-button>
  </div>

  <div *ngIf="segment == 'counter'">
    <h1 class="center">Consumption today</h1>
    <p class="center">{{ today.date }}</p>
    <p class="center">{{ today.consumption }}</p>
    <p class="center">{{ today.last_smoked }}</p>
    <ion-button expand="block" color="dark" (click)="addOne()">Add one</ion-button>
  </div>

  <div *ngIf="segment == 'history'">
    <h1 class="center">Recent consumption</h1>
    <ion-grid>
      <ion-row>
        <ion-col><b>Date</b></ion-col>
        <ion-col><b>Consumption</b></ion-col>
      </ion-row>
      <ion-row *ngFor="let history of histories">
        <ion-col>{{ history.date }}</ion-col>
        <ion-col>{{ history.consumption }}</ion-col>
      </ion-row>
      <ion-row>
        <ion-col>-{{ money_consumption_tostring  }} €</ion-col>
      </ion-row>
    </ion-grid>
  </div>

</ion-content>

interfaces: 接口:

export interface pack {
    price: number,
    cigarettecount: number
}

export interface consumption {
    date: string,
    consumption: number,
    last_smoked: string
}

home.page.ts: home.page.ts:

import { Component } from '@angular/core';
import { pack } from '../pack.interface';
import { consumption } from '../consumption.interface';
import { ConsumptionService } from '../consumption.service';

@Component({
  selector: 'app-home',
  templateUrl: 'home.page.html',
  styleUrls: ['home.page.scss'],
})
export class HomePage {

  constructor(private service: ConsumptionService) { }

  segment: string = "info";
  pack: pack[] = [];
  today = {} as consumption;
  histories: consumption[] = [];
  price: number = 0;
  money_consumption: number = 0;
  money_consumption_tostring: string = "0";

  ngOnInit() {

    this.service.getConsumptions().then((data: consumption[]) => {
      if (data == null) {
        this.today.consumption = 0;
        this.today.date = new Date().toLocaleDateString();
        this.today.last_smoked = new Date().toLocaleTimeString();
      } else {
        for (let consumption of data) {
          if (consumption.date == new Date().toLocaleDateString()) {
            this.today = consumption;
          }
        }
      }

      this.service.getConsumptions().then((data: consumption[]) => {
        this.histories = data;
      })
    })

    this.service.getPack().then((data) => {
      if (data != null) {
        this.segment = "counter";
      }
    })

  }

  addOne = () => {
    this.today.date = new Date().toLocaleDateString();
    this.today.consumption += 1;
    this.today.last_smoked = new Date().toLocaleTimeString();

    this.service.getConsumptions().then((data: consumption[]) => {
      let consumptions = data;
      // at least one consumption found
      if (consumptions != null) {
        let current_exists = false;
        for (let consumption of consumptions) {
          // use current date
          if (consumption.date == this.today.date) {
            current_exists = true;
            consumption.date = this.today.date;
            consumption.consumption = this.today.consumption;
            consumption.last_smoked = this.today.last_smoked;

            // add current consumption to history
            for (let history of this.histories) {
              if (history.date == this.today.date) {
                history.date = this.today.date;
                history.consumption = this.today.consumption;
                history.last_smoked = this.today.last_smoked;
              }
            }

          }
        }
        // new date
        if (current_exists == false) {
          consumptions.push(this.today);
          this.histories.push(this.today);
        }
        this.service.saveConsumptions(consumptions);
      } else {
        // no consumptions found
        this.service.addConsumptions(this.today);
        this.histories = data;
      }
    })
  }

  savePack = () => {
    this.service.savePack(this.pack);
    this.segment = "counter";
  }

}

consumption.service.ts: 消费。服务:

import { Injectable } from '@angular/core';
import { Storage } from '@ionic/storage';
import { pack } from './pack.interface';
import { consumption } from './consumption.interface';

@Injectable({
  providedIn: 'root'
})
export class ConsumptionService {

  constructor(private storage: Storage) { }

  getPack = () => {
    return new Promise((resolve, reject) => {
      this.storage.get("pack").then((pack) => {
        resolve(pack);
      })
    })
  }

  savePack = (pack: pack[]) => {
    this.storage.set("pack", pack);
  }

  getConsumptions = () => {
    return new Promise((resolve, reject) => {
      this.storage.get("consumption").then((kulutukset) => {
        resolve(kulutukset);
      })
    })
  }

  addConsumptions = (newconsumption: consumption) => {
    this.storage.get("consumption").then((data: consumption[]) => {
      let consumptions = data;
      let current_exists = false;
      if (consumptions == null) {
        consumptions = [{date: new Date().toLocaleDateString(), 
          consumption: 0, last_smoked: new Date().toLocaleTimeString()},
        ]
      }
      for (let consumption of consumptions) {
        // use current date
        if (consumption.date == newconsumption.date) {
          current_exists = true;
          consumption.date = newconsumption.date;
          consumption.consumption = newconsumption.consumption;
          consumption.last_smoked = newconsumption.last_smoked;
        }
      }
      // new date
      if (current_exists == false) {
        consumptions.push(newconsumption);
      }
      this.storage.set("consumption", consumptions);
    }
    )}

    saveConsumptions = (consumptions: consumption[]) => {
      this.storage.set("consumption", consumptions);
    }

}

It's important to understand how the lifecycle of a page/component works in Ionic; 了解页面/组件的生命周期在Ionic中的工作方式非常重要;

  • constructor is called before the initialisation of everything else, as soon as the component is placed; 一旦放置了组件,就在初始化所有其他组件之前调用构造函数。
  • ngOnInit (OnInit Angular event) is called ONCE when the component/page is being loaded 加载组件/页面时,将ngOnInit(OnInit Angular事件)称为ONCE
  • there are a bunch of Ionic lifecycles coming out of the box for any Ionic application as "ionViewDidLoad", "ionViewWillLoad" etc, which have all kind of different behaviours, which might actually suit your needs 对于任何Ionic应用程序,都有大量的Ionic生命周期,例如“ ionViewDidLoad”,“ ionViewWillLoad”等,它们具有各种不同的行为,实际上可能满足您的需求

As Ionic app actually stacks one page on top of the other in order to match the mobile app's standard behaviours with the back buttons and all (check the application's structure in browser devtools and try opening multiple pages), the correct way would be to hang on the Ionic lifecycles, as ionViewDidLoad or ionViewWillLoad ; 由于Ionic应用程序实际上将一页堆叠在另一页之上,以使移动应用程序的标准行为与后退按钮和所有按钮匹配(请在浏览器devtools中检查应用程序的结构并尝试打开多个页面),因此正确的方法是挂起离子生命周期,如ionViewDidLoadionViewWillLoad this event is triggered every time the view is loaded, app being re-opened or page being navigated to. 每次加载视图,重新打开应用程序或导航到页面时,都会触发此事件。

Read more here: https://blog.ionicframework.com/navigating-lifecycle-events/ 在此处阅读更多信息: https : //blog.ionicframework.com/navigating-lifecycle-events/

You can do in the constructor(){ } 您可以在constructor(){}中进行

data = [];
constructor(private storage: Storage) { 
  //write your code
  //for example:
  this.storage.get("pack").then((pack) => {
    this.data = pack;
  })
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM