【问题标题】:Ionic run function AFTER html has loaded and AFTER api callIonic 运行函数 AFTER html 已加载且 AFTER api 调用
【发布时间】:2021-11-17 23:28:56
【问题描述】:

我有一个名为 getPuzzle() 的函数,它调用 API 来获取数据。我想使用该数据来修改 div。问题是这一切都是在构造函数中完成的,所以还没有加载html。

所以我把修改 html 的代码放到了 ionViewDidEnter 中,然后它在调用 API 之前运行,并且丢失了 this.puzzle 的数据

在 HTML 完全加载和 API 调用之后,我如何才能不运行此代码?

ngOnInit() {
    this.getPuzzle();
  }

getPuzzle() {
      //Get puzzle info
      this.puzzlesService.getPuzzle().subscribe((data) => {
        this.puzzleType = this.puzzlesService.puzzleType;
        this.puzzle = this.puzzlesService.puzzle;
      });
  }

ionViewDidEnter() {
    //Set first tab
    if (this.puzzleType == 'text') {
      new Vara("#text", "assets/fonts/vara/Satisfy/SatisfySL.json", [{
        text: this.puzzle,
        delay: 2000,
        x: 2
      }], {
        fontSize: 25,
        strokeWidth: 1.5,
        duration: 15000,
        color: "black"
      });
    }

  }

【问题讨论】:

  • 在 API 调用中运行它。 this.puzzle = this.puzzlesService.puzzle; }); 在这行之后。
  • 当时没有加载 HTML,无法访问#text id
  • 你为什么订阅puzzlesService.getPuzzle(),然后忽略数据?好像很腥!另外,为什么这个组件会复制您有权访问的服务的至少 3 个属性? getPuzzlepuzzleTypepuzzle 存在于该组件和拼图服务中。这是有原因的吗?

标签: javascript angular typescript ionic-framework rxjs


【解决方案1】:

您正面临生命周期问题。因此,您可以做的一个好方法是在 Api 的结果之后调用一个函数。在您看来,您可以使用询问来避免插值时未准备好数据{{ puzzle?.text }}

ngOnInit(){
  this.getPuzzle();
}

getPuzzle() {
  //Get puzzle info
  this.puzzlesService.getPuzzle().subscribe((data) => {
    this.puzzleType = this.puzzlesService.puzzleType;
    this.puzzle = this.puzzlesService.puzzle;
    this.updateView(); ??
  });
}

updateView() {      
  //Set first tab
  if (this.puzzleType == 'text') {
  new Vara("#text", "assets/fonts/vara/Satisfy/SatisfySL.json", [{
    text: this.puzzle,
    delay: 2000,
    x: 2 }],{
    fontSize: 25,
    strokeWidth: 1.5,
    duration: 15000,
    color: "black"
  });
 }
}

【讨论】:

  • 这不起作用。因为该函数可以在 HTML 加载之前被调用并且#text 还不存在
  • 我更新了答案...所以,请看一下。在您看来,您可以使用询问来避免插值时未准备好数据 {{ puzzle?.text }}
【解决方案2】:

快速解决方案

这对于尝试使用RxJS 命令式而不是装饰性地使用非常深入(这是 RxJS 的主要代码气味)。即便如此,这是确保getPuzzle 内部的this.puzzlesService.getPuzzle()//Set first tab 运行之后的代码之前发出的一种方法。

letsGooooooo = new ReplaySubject();

ngOnInit() {
  this.getPuzzle();
}

getPuzzle() {
  //Get puzzle info
  this.puzzlesService.getPuzzle().subscribe((data) => {
    this.puzzleType = this.puzzlesService.puzzleType;
    this.puzzle = this.puzzlesService.puzzle;

    this.letsGooooooo.next("GOOOOOOO!");

  });
}

ionViewDidEnter() {

  this.letsGooooooo.pipe(
    take(1)
  ).subscribe(_ => {
    //Set first tab
    if (this.puzzleType == 'text') {
      new Vara(
        '#text',
        'assets/fonts/vara/Satisfy/SatisfySL.json',
        [
          {
            text: this.puzzle,
            delay: 2000,
            x: 2,
          },
        ],
        {
          fontSize: 25,
          strokeWidth: 1.5,
          duration: 15000,
          color: 'black',
        }
      );
    }
  });
  
}

更多涉及的解决方案

修复您的服务,以便puzzlesService 将当前拼图和拼图类型兑现为可观察对象而不是属性。那么你就不需要在本地重新实现所有这些功能了。

ngOnInit() {
  // No local version of puzzlesService needed
}

ionViewDidEnter() {

  this.puzzlesService.getPuzzle().subscribe(puzzleData => {
    //Set first tab
    if (puzzleData.puzzleType == 'text') { // puzzleData.puzzleType instead of this.puzzleType
      new Vara(
        '#text',
        'assets/fonts/vara/Satisfy/SatisfySL.json',
        [
          {
            text: puzzleData.puzzle, // puzzleData.puzzle instead of this.puzzle
            delay: 2000,
            x: 2,
          },
        ],
        {
          fontSize: 25,
          strokeWidth: 1.5,
          duration: 15000,
          color: 'black',
        }
      );
    }
  });
  
}

【讨论】:

  • 似乎我也不能使用 ionviewdidenter。如果我只是在没有任何变量的情况下运行 vara 代码,那么在 dom 加载之前还不够长,并且 #text 仍然不存在。你知道是否需要等待一个 div 存在然后执行代码?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多