angular - 为什么我在覆盖字符串时会重复添加字符串?
问题描述
我的目标:从组件调用服务中的函数,它将返回一个字符串数组。
我第一次得到一个数组没问题。如: 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;
}
}
解决方案
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 i
th 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.
推荐阅读
- javascript - 将从 Javascript 发送的列表映射到 Java 后端
- r - R中的数据转换 - 傻瓜
- php - 按特定键过滤多维数组并创建子数组PHP?
- c++ - INT 如何在 C++ 中返回为 INT&?
- swift - 重建失败 HelloPhotogrammetry 错误
- javascript - 如何解决javascript中的模板文字问题?
- sql - Oracle:从结果集 ID 生成 WHERE 子句?
- django - DRF:是否可以进行双面对象创建和关系分配?
- python - Python根据另一个excel表中的关键词对excel中的数据进行分类
- c++ - SWIG LUA C++ 包装器