在 Angular 中,我如何动态地将某些单词包装在另一个 html 元素中?
Posted
技术标签:
【中文标题】在 Angular 中,我如何动态地将某些单词包装在另一个 html 元素中?【英文标题】:In Angular how do I dynamically wrap certain words in another html element? 【发布时间】:2020-06-06 03:21:27 【问题描述】:我有这个简单的 Angular 组件:
@Component(
selector: 'my-component',
template: '<p>someString</p>',
)
export class MyComponent
@Input() someString: string;
someString
可以是任意长度的任意字符串。例如,假设someString
的值为:
"If you want my body and you think I'm sexy, come on, sugar, tell me so."
在这种情况下,Angular 生成的 html 基本上等同于:
<p>If you want my body and you think I'm sexy, come on, sugar, tell me so.</p>
我将如何修改MyComponent
,以便它检测someString
中每个出现的单词sexy
,并让Angular 将该单词包装在另一个HTML 元素中,例如<b>
。所以在这个例子中,它会产生类似的东西:
<p>If you want my body and you think I'm <b>sexy</b>, come on, sugar, tell me so.</p>
如果我想将每个出现的单词 sexy
包装在 Angular 组件中而不是原生 HTML 元素中怎么办?是否需要采用不同的方法?
【问题讨论】:
可以在句子中搜索单词,然后分别在其前后注入开始和结束标签。 @NicholasK 我如何注入开始和结束标签? 我添加了一个答案,或者与另一个答案相同。 (IMO,另一个更好!)删除了我的,因为它太复杂了.. 嗨 - 我已经完成了你的要求:包装在另一个角度标签中。这很糟糕。我最终不得不首先将尝试将文本包装在其中的角度组件(在本例中为此解决方案避免使用 innerHTML
并严格依赖 Angular 构造。
@Component(
selector: 'my-component',
template: `
<p>
<ng-container *ngFor="let segment of segments">
<span *ngIf="!segment.shouldBeBold()">segment.text</span>
<b *ngIf="segment.shouldBeBold()">segment.text</b>
</ng-container>
</p>
`,
)
export class MyComponent
@Input() someString: string;
private wordsToBold = new Set(['sexy', 'body', 'sugar']);
get segments()
const regex = this.makeRegex();
const segments = this.someString.split(regex);
return segments.map(segment =>
return text: segment, shouldBeBold: wordsToBold.has(segment.toLowerCase()) ;
);
private makeRegex()
const expression = [...this.wordsToBold].join('\\b|\\b');
return new RegExp(`(\\b$expression\\b)+`, 'gi');
【讨论】:
【参考方案2】:你可以使用类似下面的东西——在渲染主句之后,你可以用一个 span 元素替换特殊词并应用一个 CSS 类,比如 .special
到那个 span 标签。
从 '@angular/core' 导入 Component, Input, ElementRef, AfterViewInit ;
@Component(
selector: 'my-component',
template: '<p>sentence</p>'
)
export class MyComponent implements AfterViewInit
@Input() sentence: string;
@Input() specialWord: string;
constructor(private el: ElementRef)
ngAfterViewInit()
this.el.nativeElement.innerHTML = this.el.nativeElement.
innerHTML.replace(new RegExp(`$this.specialWord`, 'g'),
`<span class="special">$this.specialWord</span>`);
为了使您的代码保持通用性,您可以使用额外的@Input()
来表示特殊字词。
在您的应用程序的styles.scss
中,您可以定义CSS 类.special
。
.special
font-weight: bold;
如果您想知道为什么不能使用类似的逻辑将sentence
的内容替换为如下内容:
this.sentence = this.sentence.replace(new RegExp(`$this.specialWord`, 'g'),
`<span class="special">$this.specialWord</span>`);
然后,请注意 Angular 将转义 HTML 标签,它们将按原样出现在输出中。所以你会在浏览器中看到类似这样的东西,而不是样式化的 span。
Hello, it's a <span class="special">beautiful</span> day and I am in a very <span class="special">beautiful</span> city
这就是为什么,我不得不求助于操纵 innerHTML
以便在 Angular 将句子渲染到 DOM 后完成替换。
【讨论】:
我认为在使用像 Angular 这样的框架时,以这种方式修改 innerHTML 有点不受欢迎?我弄错了吗? 你的问题也比较奇特,不知道有没有其他方法可以解决。 @snowfrogdev 确实如此,但对于简单的 html 来说基本上没问题。要执行更多操作,您需要使用 sanitizeDom angular.io/api/platform-browser/DomSanitizer 所以我猜这个解决方案在我不想将单词包装在 我想将它包装在我自己的 Angular 组件中的情况下不起作用?【参考方案3】:你可以试试这个:D
@Component(
selector: 'app-test',
template: `
<p [innerHTML]="stringFormatted()"></p>
`,
styles: []
)
export class TestComponent
someString = "If you want my body and you think I'm sexy, come on, sugar, tell me so.";
stringFormatted()
return this.someString.replace(/sexy/g, '<b>sexy</b>');
【讨论】:
我认为在使用像 Angular 这样的框架时,以这种方式修改 innerHTML 有点不受欢迎?我弄错了吗? 对我来说,这是满足您要求的最简单方法。 真的,我不确定是否有更好的方法。如果字符串是从外部源加载的,你应该通过 DOMsanitizer 传递它,但我认为使用它没有问题。 @snowfrogdev :您可以阅读DOM Sanitization 以确保没有恶意软件被注入。 所以我猜这个解决方案在我不想将单词包装在 我想将它包装在我自己的 Angular 组件中的情况下不起作用?以上是关于在 Angular 中,我如何动态地将某些单词包装在另一个 html 元素中?的主要内容,如果未能解决你的问题,请参考以下文章