Angular中获取textarea删除文本及@提及词删除处理需求
Angular 捕获文本删除内容及@提及词自动删除方案
核心思路
要覆盖所有删除场景(Backspace/Delete、选中替换、剪切、全选清除),不能仅依赖键盘事件,必须通过对比文本前后状态捕获被删内容;针对@提及词,通过正则匹配识别提及范围,检测部分删除行为时自动移除整个提及词。
实现步骤及代码
1. 模板结构
绑定双向数据及关键事件,覆盖所有内容变更场景:
<textarea [(ngModel)]="textContent" (input)="handleTextInput()" (keydown.backspace)="handleKeyDown($event)" (keydown.delete)="handleKeyDown($event)" (cut)="handleCut($event)" rows="5" ></textarea>
2. 组件核心逻辑
定义必要变量及处理函数:
import { Component } from '@angular/core'; @Component({ selector: 'app-textarea-delete-handler', templateUrl: './textarea-delete-handler.component.html', styleUrls: ['./textarea-delete-handler.component.css'] }) export class TextareaDeleteHandlerComponent { textContent: string = ''; prevTextContent: string = ''; // 可根据需求调整提及词正则,比如允许特殊字符 private mentionRegex: RegExp = /@[\w\-_]+/g; /** * 处理文本变更(覆盖输入、删除、替换、粘贴等所有场景) */ handleTextInput(): void { // 捕获被删除内容及所属单词 const deletedContent = this.getDeletedContent(this.prevTextContent, this.textContent); if (deletedContent) { const relatedWords = this.getRelatedWords(this.prevTextContent, deletedContent); // 这里可根据业务需求处理结果(比如上报、存储) console.log('被删内容:', deletedContent, '所属单词:', relatedWords); } // 检测并处理@提及词的部分删除 this.handlePartialMentionDeletion(); // 更新历史文本状态 this.prevTextContent = this.textContent; } /** * 处理Backspace/Delete键,针对光标在提及词内部的情况直接删除整个词 */ handleKeyDown(event: KeyboardEvent): void { const textarea = event.target as HTMLTextAreaElement; const cursorPos = textarea.selectionStart; const currentText = textarea.value; // 检查光标是否处于某个提及词内部 const mentions = currentText.match(this.mentionRegex) || []; for (const mention of mentions) { const startIdx = currentText.indexOf(mention); const endIdx = startIdx + mention.length; if (cursorPos > startIdx && cursorPos < endIdx) { event.preventDefault(); // 删除整个提及词 this.textContent = currentText.slice(0, startIdx) + currentText.slice(endIdx); // 重置光标位置到提及词原起始处 setTimeout(() => { textarea.selectionStart = startIdx; textarea.selectionEnd = startIdx; }, 0); this.prevTextContent = this.textContent; break; } } } /** * 处理剪切事件,直接捕获选中的剪切内容 */ handleCut(event: ClipboardEvent): void { const textarea = event.target as HTMLTextAreaElement; const selectedText = textarea.value.substring(textarea.selectionStart, textarea.selectionEnd); if (selectedText) { const relatedWords = this.getRelatedWords(this.prevTextContent, selectedText); console.log('被剪切内容:', selectedText, '所属单词:', relatedWords); } } /** * 对比前后文本,找出被删除的内容 */ private getDeletedContent(prevText: string, currentText: string): string | null { if (currentText.length >= prevText.length) return null; // 匹配最长公共前缀 let prefixLen = 0; while (prefixLen < prevText.length && prefixLen < currentText.length && prevText[prefixLen] === currentText[prefixLen]) { prefixLen++; } // 匹配最长公共后缀 let suffixLen = 0; while (suffixLen < prevText.length - prefixLen && suffixLen < currentText.length - prefixLen && prevText[prevText.length - 1 - suffixLen] === currentText[currentText.length - 1 - suffixLen]) { suffixLen++; } return prevText.slice(prefixLen, prevText.length - suffixLen); } /** * 找出被删内容所属的单词(按空格分割) */ private getRelatedWords(fullText: string, deletedContent: string): string[] { const words = fullText.split(/\s+/); return words.filter(word => word.includes(deletedContent)); } /** * 检测@提及词是否被部分删除,若是则自动删除整个提及词 */ private handlePartialMentionDeletion(): void { const prevMentions = this.prevTextContent.match(this.mentionRegex) || []; const currentMentions = this.textContent.match(this.mentionRegex) || []; prevMentions.forEach(mention => { // 原提及词已不存在,且当前文本包含该提及词的部分内容 if (!currentMentions.includes(mention) && (this.textContent.includes(mention.slice(0, -1)) || this.textContent.includes(mention.slice(1)))) { const mentionIdx = this.prevTextContent.indexOf(mention); // 删除整个提及词并清理多余空格 this.textContent = this.prevTextContent.slice(0, mentionIdx) + this.prevTextContent.slice(mentionIdx + mention.length); this.textContent = this.textContent.replace(/\s+/g, ' ').trim(); this.prevTextContent = this.textContent; } }); } }
关键说明
- 全场景删除捕获:通过
input事件结合前后文本对比,覆盖所有删除/剪切/替换操作,解决单一键盘事件无法覆盖所有场景的问题。 - 提及词处理:
- 键盘删除时,若光标在提及词内部,直接阻止默认行为并删除整个提及词。
- 选中替换/部分删除提及词时,通过对比前后提及词列表,检测部分删除行为并自动移除整个提及词。
- 扩展性:可根据业务需求调整
mentionRegex正则规则,或修改getRelatedWords的单词分割逻辑(比如支持其他分隔符)。
内容的提问来源于stack exchange,提问作者Zia Khan
相关产品推荐
相关产品推荐

