You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Angular中通过自定义指令实现matInput输入框关键词高亮

需求可行性说明

首先明确:原生<input>标签属于纯文本输入控件,value属性仅支持纯文本内容,插入的HTML标签会被直接当作字符串渲染,因此你当前的写法无法实现效果,但该需求本身可通过调整实现方案完成。


具体实现方案

方案1:使用contenteditable元素模拟输入框(最简便)

利用contenteditable属性的元素支持渲染内部HTML的特性,配合matInput样式模拟输入效果,适配Angular表单逻辑即可。

步骤1:修改模板代码

<mat-form-field>
  <mat-label>keyword:</mat-label>
  <!-- 替换原生input为contenteditable的div,保留matInput属性 -->
  <div 
    matInput 
    formControlName="keyword" 
    appKeywordHighlight
    contenteditable="true"
  ></div>
</mat-form-field>

步骤2:调整自定义指令代码

import {Directive, Renderer2, OnInit, ElementRef, Input} from '@angular/core';
import { DomSanitizer, SafeHtml, SecurityContext } from '@angular/platform-browser';
import { NgControl } from '@angular/forms';

@Directive({
  selector: '[appKeywordHighlight]'
})
export class KeywordHighlightDirective implements OnInit {
  // 外部传入要高亮的关键词
  @Input() highlightKeyword: string = '';

  constructor(
    private renderer: Renderer2,
    private elRef: ElementRef,
    private _sanitizer: DomSanitizer,
    private ngControl: NgControl // 注入表单控制器,实现双向绑定,不需要对接表单可移除
  ) { }

  ngOnInit() {
    // 监听输入事件,同步内容到表单控件,不需要对接表单可移除
    this.renderer.listen(this.elRef.nativeElement, 'input', () => {
      const rawText = this.elRef.nativeElement.innerText;
      this.ngControl.control?.setValue(rawText);
      // 输入时实时更新高亮
      this.updateHighlight(rawText);
    });

    // 初始化渲染带高亮的内容
    const initText = this.ngControl.control?.value || '';
    this.updateHighlight(initText);
  }

  private updateHighlight(rawText: string) {
    if (!this.highlightKeyword || !rawText) {
      this.elRef.nativeElement.innerHTML = rawText;
      return;
    }
    // 转义关键词特殊字符,避免正则报错
    const escapedKeyword = this.highlightKeyword.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
    // 匹配到的关键词包上带高亮类的span
    const highlightedHtml = rawText.replace(
      new RegExp(escapedKeyword, 'gi'),
      match => `<span class="highlight-keyword">${match}</span>`
    );
    // 处理HTML避免安全风险
    this.elRef.nativeElement.innerHTML = this._sanitizer.sanitize(SecurityContext.HTML, highlightedHtml);
  }

} //end class

步骤3:添加高亮样式

在全局样式或者组件样式中添加:

.highlight-keyword {
  background-color: #ffeb3b;
  color: #000;
  border-radius: 2px;
  padding: 0 2px;
}
/* 消除contenteditable的默认外边框 */
[contenteditable]:focus {
  outline: none;
}

方案2:层叠遮罩方案(无侵入式适配原生input)

如果需要保留原生input的所有特性(比如密码输入、原生表单校验等),可以做两层结构:上层是透明的原生input负责接收输入,下层是和input样式完全一致的div负责渲染带高亮的HTML内容,输入时同步两侧文本即可,这种方案不需要修改原有表单绑定逻辑。


原有代码问题说明

你之前直接给input的value赋值带<span>的字符串,原生input会将所有内容识别为纯文本,不会解析HTML标签,因此会直接显示标签内容,属于预期行为。

内容的提问来源于stack exchange,提问作者Tampa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 18:36:08