首页 > 解决方案 > 为什么我在覆盖字符串时会重复添加字符串?

问题描述

我的目标:从组件调用服务中的函数,它将返回一个字符串数组。

我第一次得到一个数组没问题。如: http://localhost:4200/assets/images/hardwoods/american_white_oak.png

但是,当我浏览到另一个页面并再次访问同一页面时,我会得到一个附加的数组: http://localhost:4200/assets/images/hardwoods/american_white_oak.png.png (重复的“.png”)。

我不明白为什么每次更改页面时组件中的数组图像都没有被覆盖,为什么如果它没有被覆盖 - 为什么只添加“.png”字符串?

关于这部分代码的简短说明: 我正在调用服务中的函数。这个函数是: 1.创建一个新的字符串数组,从一个模型中的一个对象分配一个数组给它。该对象由服务内部的构造函数创建。2. 在其上和内部运行 for 循环:进行一些拆分/加入。小写从左到右添加一个字符串。退出 for 循环。3. 返回修改后的数组。

组件的html文件

<ngb-carousel #carousel interval="3000" [pauseOnHover]="pauseOnHover" (slide)="onSlide($event)">
<ng-template ngbSlide *ngFor="let img of images; index as i">
  <div class="carousel-caption">
    <h3>{{imageNames[i]}}</h3>
  </div>
  <div class="picsum-img-wrapper">
    <img [src]="img" alt="img">
  </div>
</ng-template>  

组件的 TS

import { Component, ViewChild, OnInit } from '@angular/core';
import { NgbCarousel, NgbSlideEvent, NgbSlideEventSource } from '@ng-bootstrap/ng-bootstrap';
import { ImageService } from 'src/app/services/image.service';
import { from } from 'rxjs';


@Component({
  selector: 'app-hardwood-heb',
  templateUrl: './hardwood-heb.component.html',
  styleUrls: ['./hardwood-heb.component.css'],

})
export class HardwoodHebComponent implements OnInit {

  public images: string[] = new Array<string>();
  public imageNames: string[] = new Array<string>();
  unpauseOnArrow: boolean = false;
  paused: boolean = false;
  pauseOnHover: boolean = true;

  constructor(private imageService: ImageService) {

  }
  ngOnInit() {
    this.images=[];
    this.imageNames = this.imageService.getImageName();
    this.images = this.imageService.getHardwoodImagesPath();
    this.images.forEach(element => {
      console.log(element);
    });

  }




  @ViewChild('carousel', { static: true }) carousel: NgbCarousel;

  togglePaused() {
    if (this.paused) {
      this.carousel.cycle();
    } else {
      this.carousel.pause();
    }
    this.paused = !this.paused;

  }

  onSlide(slideEvent: NgbSlideEvent) {
    if (this.unpauseOnArrow && slideEvent.paused &&
      (slideEvent.source == NgbSlideEventSource.ARROW_LEFT || slideEvent.source == NgbSlideEventSource.ARROW_RIGHT)) {
      this.togglePaused();
    }
    if (!slideEvent.paused && slideEvent.source == NgbSlideEventSource.INDICATOR) {
      this.togglePaused();
    }
  }

}

模型

export class Hardwood {
    public readonly name: Array<string> = ['אגוז אפריקאי','אגוז אמריקאי','אורן קרולינה','אורן קליר','אלון אדום אמריקאי',
    'אלון לבן אמריקאי','אלון אירופאי','בוק מוקצע','מייפל הארד','ספלי מהגוני','פופלר','דובדבן \ שרי','אשה'];
    // Altname uses also for path name!
    public readonly altName: Array<string> =['African Black Ofram','American Walnut','American Southern yellow pine','American Duglas fir','American Red Oak',
    'American White Oak','European Oak','European Beechwood','American Hard Maple','African Mahagoni Sapelli','American Yellow Poplar','American Cherry','American White Ash'];


}

服务

import { Hardwood } from 'src/app/models/hardwood';
import { Injectable } from '@angular/core';

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

  constructor(private hardwoods:Hardwood) { }

  public getHardwoodImagesPath():string[]{
    let str: string[] = this.hardwoods.altName;
    for ( var i = 0; i < str.length; i++ ){
      str[i] = str[i].split(' ').join('_');
      str[i] = str[i].toLocaleLowerCase();
      str[i] = `../../../assets/images/hardwoods/${str[i]}.png`;
    }
    return str;
  }

  public getImageName():string[]{
    return this.hardwoods.name; 
  }
}

标签: angularduplicates

解决方案


You're modifying your original array.

The simplest fix you can make is to take a copy of the hardwoods array using slice. This will make a copy of the array that you can safely work with without modifying the original.

public getHardwoodImagesPath():string[]{
  const str: string[] = this.hardwoods.altName.slice();
  for (let i = 0; i < str.length; i++) {
    str[i] = str[i].split(' ').join('_');
    str[i] = str[i].toLocaleLowerCase();
    str[i] = `../../../assets/images/hardwoods/${str[i]}.png`;
  }
  return str;
}

The reason why

When you do this:

const str: string[] = this.hardwoods.altName;

You are only copying the reference to the original array. It's no different to working with the original array directly. So when you do this:

str[i] = str[i].split(' ').join('_');

You are actually updating the ith entry in the original array.

Using map

You could improve this by combining the loop and the mapping into one function by using the array function map.

public getHardwoodImagesPath():string[]{
  const path = '../../../assets/images/hardwoods/';
  return this.hardwoods.altName.
    .map(x => `${path}${x.replace(/ /g, '_').toLowerCase()}.png`);
}

This is combining the loop, the string replacement, and a new array. It is far more efficient that my first answer - I just wanted to highlight the issue rather than get distracted by other improvements.


推荐阅读