【问题标题】:Highlight multiple strings in a statement - Javascript在语句中突出显示多个字符串 - Javascript
【发布时间】:2023-04-07 05:41:02
【问题描述】:

我需要在 HTML 的语句中突出显示多个单词。

Ex: words: ['Hello', 'world', 'my']  
Statement: 'Hello, welcome to my beautiful world'

我可以在正常情况下使用正则表达式查找和替换来做到这一点(比如用一些标记替换每个单词的出现,比如

<span  class="highlight-span"> word </span>.    

但问题是,如果我的替换标记字符串中有任何诸如 spa、span、class、lass、high 之类的词,我会遇到问题。)

有什么想法可以更好地做到这一点吗?

以下是供您参考的代码。

import {
    Pipe,
    PipeTransform
} from '@angular/core';
@Pipe({
    name: 'highlight'
})
export class HighlightSearch implements PipeTransform {
    transform(value: string, args: string): any {
        if (args && value) {
            let startIndex = value.toLowerCase().indexOf(args.toLowerCase());
            if (startIndex != -1) {
                let endLength = args.length;
                let matchingString = value.substr(startIndex, endLength);
                return value.replace(matchingString, "<span  class="highlight-span">" + matchingString + "</span>");
            }

        }
        return value;
    }
}

在这种情况下,我不能使用诸如 mar、mark 之类的搜索词。我怎样才能摆脱这些问题?

【问题讨论】:

  • 你可以为它创建一个 StackBlitz 吗?我无法复制您的问题。即使我使用 mar, mark 作为搜索字符串,它似乎也能正常工作。
  • 这是处理单个搜索字符串的示例代码。如果我发送多个字符串并循环重复,以防我的第二个字符串是 'mar' 时 将出现在语句中!希望你现在明白了。 @nash11

标签: javascript html angular vue.js


【解决方案1】:

这是使用RegExp 执行此操作的更简单的方法

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
    name: 'highlight'
})
export class HighlightPipe implements PipeTransform {

    transform(value: string, args: string[] | string): string {
        if (!args.length) { return value; }
        const pattern = Array.isArray(args) ? args.filter(arg => !!arg).join('|') : args;
        const regex = new RegExp(pattern.concat('|<[^>]*>'), 'gi');
        return value.replace(regex, (match) => /<[^>]*>/g.test(match) ? match: `<mark>${match}</mark>`);
    }

}

我已经制作了管道,以便您可以在需要时使用两个数组或单个字符串突出显示。 &lt;[^&gt;]*&gt; 是用于匹配 HTML 标签的 RegEx。

如果您想区分大小写进行搜索,只需在创建RegExp 时删除i,如下所示

const regex = new RegExp(pattern.concat('|<[^>]*>'), 'g');

然后在您的模板中,使用如下管道

<span [innerHTML]="sentence | highlight: highlightWords"></span>

sentencehighlightWords 在哪里

sentence: string = 'Hello, welcome to my beautiful world';
highlightWords: string[] = ['world', 'my'];

更新:我注意到管道在使用元字符时不起作用。要解决此问题,请使用正则表达式转义元字符,如 here 所示。

const pattern = Array.isArray(args) ? args.filter(arg => !!arg).map(this.escapeRegex).join('|') : this.escapeRegex(args);

函数escapeRegex定义为

escapeRegex(word: string) {
    return word.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
}

这是StackBlitz 上的一个工作示例。

【讨论】:

  • 它可以部分工作,因为如果文本已经有一个标记标签,则会失败。即句子:string = '你好,欢迎标记我美丽的世界';
  • 谢谢@nash11,用 标签替换它很有效。有没有办法用&lt;span class="highlight-span"&gt; word &lt;/span&gt; 之类的东西代替它。我不清楚我的示例代码。我现在已经更新了。
  • 你可以把&lt;mark&gt;${match}&lt;/mark&gt;换成&lt;span class="highlight-span"&gt;${match}&lt;/span&gt;
  • 是的,刚刚验证过了。像魅力一样工作。棒呆了的家伙。非常感谢。
【解决方案2】:

快速粗暴的方法

import {
    Pipe,
    PipeTransform
} from '@angular/core';
import {
    DomSanitizer
} from '@angular/platform-browser'

    @Pipe({
        name: 'highlight'
    })
    export class HighlightSearch implements PipeTransform {

        constructor(private sanitizer: DomSanitizer){}

        transform(value: string, args: string): any {
            if (args && value) {
                let startIndex = value.toLowerCase().indexOf(args.toLowerCase());
                if (startIndex != -1) {
                    let endLength = args.length;
                    let matchingString = value.substr(startIndex, endLength);
                    let temp = value.replace("<mark>", "START_PLACEHOLDER");
                    temp = temp.replace("</mark>", "END_PLACEHOLDER");
                    temp = temp.replace(matchingString, "<mark>" + matchingString + "</mark>");
                    temp = temp.replace( "START_PLACEHOLDER","<mark>");
                    temp = temp.replace( "END_PLACEHOLDER","</mark>");
                    return this.sanitizer.bypassSecurityTrustHtml(temp)
                }

            }
            return value;
        }
    }

当你像这样插入 html 时也使用 Dom Sanitizer

【讨论】:

    猜你喜欢
    • 2015-01-30
    • 2010-12-01
    • 2021-09-12
    • 2021-09-25
    • 1970-01-01
    • 1970-01-01
    • 2012-03-09
    • 2011-09-04
    • 2022-12-07
    相关资源
    最近更新 更多