如何用JavaScript实现[[Tag]]输入自动重复并解决重复触发及标签加粗需求
问题与解决方案
需求概述
- 表单输入
[[标签名]]格式内容时,自动重复为[[标签名]][[标签名]],方便在两个标签间插入内容 - 支持带空格的标签(如
[[Tag 2]]、[[Tag 3]]) - 标签需要加粗显示
- 修复现有代码持续重复标签的bug
修复方案
核心思路
- 用正则精准匹配未被重复过的
[[标签]],避免每次输入都触发重复逻辑 - 使用富文本容器(
contenteditable)实现原生加粗效果,或在普通输入框中用Markdown加粗语法 - 自动将光标定位到两个标签中间,提升输入体验
完整代码实现(富文本版)
HTML部分(替换原输入框)
<div id="note_text" contenteditable="true" style="border:1px solid #ccc; padding:8px; min-height:100px;"></div> <button id="new_note_button">新建笔记</button> <div id="new_note_form_container" style="display:none;"> <!-- 其他表单内容 --> </div>
JavaScript部分
function newNote() { const note_button = document.getElementById("new_note_button"); const note = document.getElementById("new_note_form_container"); if (note.style.display === "none") { note.style.display = "block"; note_button.innerHTML = "仅显示笔记"; } else { note.style.display = "none"; note_button.innerHTML = "新建笔记"; } } document.addEventListener('DOMContentLoaded', function(){ const input_note = document.getElementById('note_text'); input_note.addEventListener('input', handleTagDuplication); }); function handleTagDuplication(ev) { const target = ev.target; // 匹配未重复的[[标签]]:匹配[[内容]]且后面没有紧跟着相同的[[内容]] const tagRegex = /\[\[([^\]]+)\]\](?!\[\[\1\]\])/g; let updatedContent = target.innerHTML; let match; // 遍历所有符合条件的标签 while ((match = tagRegex.exec(updatedContent)) !== null) { const tagContent = match[1]; const fullTag = match[0]; // 替换为两个加粗的标签 const replacement = `<strong>${fullTag}</strong><strong>${fullTag}</strong>`; updatedContent = updatedContent.replace(fullTag, replacement); // 重置正则索引,避免死循环 tagRegex.lastIndex = match.index + replacement.length; } // 仅在内容变化时更新,避免频繁触发 if (updatedContent !== target.innerHTML) { target.innerHTML = updatedContent; // 将光标移动到最后一组标签的中间 const selection = window.getSelection(); const range = document.createRange(); const secondTags = target.querySelectorAll('strong:nth-child(even)'); if (secondTags.length > 0) { const lastSecondTag = secondTags[secondTags.length - 1]; range.setStartBefore(lastSecondTag); range.collapse(true); selection.removeAllRanges(); selection.addRange(range); } } }
普通文本框版(Markdown加粗)
如果需要使用<textarea>或<input>,可以用Markdown的**语法实现加粗:
function handleTagDuplication(ev) { const target = ev.target; let value = target.value; // 匹配未重复的[[标签]] const tagRegex = /\[\[([^\]]+)\]\](?!\[\[\1\]\])/g; let updatedValue = value; let match; while ((match = tagRegex.exec(value)) !== null) { const tagContent = match[1]; const fullTag = match[0]; // 替换为两个加粗的Markdown标签 const replacement = `**${fullTag}** **${fullTag}**`; updatedValue = updatedValue.replace(fullTag, replacement); } if (updatedValue !== value) { target.value = updatedValue; // 定位光标到两个标签中间 const lastTagPos = updatedValue.lastIndexOf('**[['); if (lastTagPos !== -1) { const cursorPos = lastTagPos + `**[[${tagContent}]]**`.length; target.setSelectionRange(cursorPos, cursorPos); } } }
关键说明
- 正则
(?!\[\[\1\]\])是负向预查,确保只处理还没被重复的标签,解决持续重复的bug - 富文本版用
<strong>标签实现原生加粗,视觉效果更直观 - 光标自动定位功能让用户无需手动移动光标,直接在标签间输入内容
内容的提问来源于stack exchange,提问作者RoyKeane94
相关产品推荐
相关产品推荐

