马黑黑 发表于 2026-7-6 20:57

textarea模拟高亮关键字

<div class="hEdiv" data-prev="1"><pre class="hEpre">
&lt;style&gt;
    .tMid { text-align: center; }
    .hlight { background: tan; }
    /* 编辑区域容器 */
    .wrap {
      width: 600px;
      height: 460px;
      box-sizing: border-box;
      padding: 0;
      margin: 20px auto 0;
      position: relative;
    }
    /* 编辑区域内 pre 和 textarea 核心属性 */
    .edCommon {
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      font: normal 18px/24px Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
      background: none;
      white-space: pre-wrap;
      word-break: break-all;
      box-sizing: border-box;
      overflow: auto;
      border: 1px solid gray;
      outline: none;
      resize: none;
      padding: 12px;
      margin: 0;
      transition: 1s;
    }
    /* pre 初始状态 */
    #pre { color: blue; transform: translate(-50%, 0); }
    /* textarea 初始状态 */
    #ta { color: black; transform: translate(50%, 0); }
&lt;/style&gt;

&lt;h2 class="tMid"&gt;textarea模拟高亮关键字&lt;/h2&gt;
&lt;p class="tMid"&gt;检验方法:在文本框输入任何文字后选择任意文字,匹配选择文字的字符将以背景高亮的形式呈现。编辑区内两个元素合并、分离状态下均可操作。&lt;/p&gt;
&lt;!-- 编辑区 :pre 在前 textarea 在后 --&gt;
&lt;div class="wrap"&gt;
    &lt;pre id="pre" class="edCommon"&gt;pre&lt;/pre&gt;
    &lt;textarea id="ta" class="edCommon" placeholder="请输入 ..."&gt;&lt;/textarea&gt;
&lt;/div&gt;
&lt;p class="tMid"&gt;&lt;button onclick="separateElms(this)"&gt;合并&lt;/button&gt;&lt;/p&gt;

&lt;script&gt;
    let keyword = ''; // 查找关键词

    // 辅助演示 :两个元素的 分离/叠加
    function separateElms(btn) {
      if (btn.textContent === '分离') {
            ta.style.transform = 'translate(50%, 0)';
            pre.style.transform = 'translate(-50%, 0)';
            pre.style.color = 'blue';
      } else {
            ta.style.transform = 'translate(0, 0)';
            pre.style.transform = 'translate(0, 0)';
            pre.style.color = 'transparent';
      }
      btn.textContent = btn.textContent === '分离' ? '合并' : '分离';
    }
   
    function syncScroll(e) {
      const targetElm = e.target === pre ? ta : pre;
      targetElm.scrollTop = e.target.scrollTop;
      targetElm.scrollLeft = e.target.scrollLeft;
    }
   
    // 核心函数 :高亮关键词函数
    function hlight() {
      if (!ta.value) {
            pre.innerHTML = '';
            return;
      }
      // 处理 textarea 内容(转义尖括号)
      let code = ta.value.replaceAll('&lt;', '&amp;lt;').replaceAll('&gt;', '&amp;gt;');
      // 若查找关键词存在高亮所有匹配的关键词
      if (keyword) code = code.replaceAll(
            keyword,
            `&lt;span class="hlight"&gt;${keyword}&lt;/span&gt;`
      );
      pre.innerHTML = code; // 处理结果呈现在 pre 里
    }
   
    ta.oninput = () =&gt; hlight(); // textarea 输入时处理高亮关键字
      
    ta.onscroll = (e) =&gt; syncScroll(e); // 滚动同步
   
    pre.onscroll = (e) =&gt; syncScroll(e); // 滚动同步
   
    // 编辑框选择事件
    ta.onmouseup = () =&gt; {
      const start = ta.selectionStart;
      const end = ta.selectionEnd;
      if (start === end) return;
      keyword = ta.value.substring(start, end);
      if (keyword) hlight(); // 有关键词高亮显示
    };
&lt;/script&gt;
</pre></div>

<script type="module">
    import hl from 'https://638183.freep.cn/638183/web/js/hl.js';
    const divs = document.querySelectorAll('.hEdiv');
    const pres = document.querySelectorAll('.hEpre');
    divs.forEach((div,idx) => hl.hl(div, pres));
</script>

马黑黑 发表于 2026-7-6 21:02

说明:

(一)textarea 自身只支持一个全局背景色、一个全局文本色,它并不能高亮渲染所有匹配的查找关键词;

(二)本例利用叠加技术将一个 pre 和 一个 textarea 放在一起(演示效果中的“合并状态)。pre 元素可以较好地和 textarea 元素共享核心 CSS 属性;

(三)可能存在的问题:textarea 的 value 转到 pre 中,在 pre 中实现高亮关键词效果,必须使用 HTML 格式,这对绝大多数文本没问题,但如果 textarea 的文本是复杂的相关代码,因为转移问题可能会出现偏差,因此上例中简单的尖括号转义可能达不到要求。

红影 发表于 2026-7-6 21:38

复制了一段文字,这个能很好地找到相同的字,真方便啊{:4_187:}

马黑黑 发表于 2026-7-6 21:48

红影 发表于 2026-7-6 21:38
复制了一段文字,这个能很好地找到相同的字,真方便啊
这个演示对普通文本的匹配和高亮没问题,但对特殊文本的处理机制还远远不够,需要深入处理。

但这个仅是简单演示,个人认为:限于篇幅和水平问题,就酱紫吧。

霜染枫丹 发表于 2026-7-8 01:10

我若是想写点小资一类的文案,一定会选择这样处理一些高亮字,便捷好用。感谢分享,马老师晚上好!{:4_204:}{:4_190:}

红影 发表于 2026-7-8 10:05

马黑黑 发表于 2026-7-6 21:48
这个演示对普通文本的匹配和高亮没问题,但对特殊文本的处理机制还远远不够,需要深入处理。

但这个仅 ...

能匹配普通文本就很好很实用啊,我们又不做复杂文本{:4_173:}

马黑黑 发表于 2026-7-10 19:12

红影 发表于 2026-7-8 10:05
能匹配普通文本就很好很实用啊,我们又不做复杂文本

其实所谓的复杂文本,指的是 HTML 实体,例如:

<、&gt;、&amp;gt 之类的东东,这些东东远超乎想象,非常复杂

马黑黑 发表于 2026-7-10 19:13

霜染枫丹 发表于 2026-7-8 01:10
我若是想写点小资一类的文案,一定会选择这样处理一些高亮字,便捷好用。感谢分享,马老师晚上好!{:4_204: ...

那个,HTML的话,通过设置 <mark>高亮文字</mark> 即可,并不复杂

杨帆 发表于 2026-7-10 19:45

很实用,尤其批量查找关键词,谢谢马老师精彩分享{:4_190:}

马黑黑 发表于 2026-7-11 12:15

杨帆 发表于 2026-7-10 19:45
很实用,尤其批量查找关键词,谢谢马老师精彩分享

{:4_180:}

红影 发表于 2026-7-12 09:11

马黑黑 发表于 2026-7-10 19:12
其实所谓的复杂文本,指的是 HTML 实体,例如:

看着就觉得好复杂啊。

马黑黑 发表于 2026-7-12 17:29

红影 发表于 2026-7-12 09:11
看着就觉得好复杂啊。

关键是,不做处理的话,它们会乱窜或根本就无法匹配命中

红影 发表于 2026-7-14 19:29

马黑黑 发表于 2026-7-12 17:29
关键是,不做处理的话,它们会乱窜或根本就无法匹配命中

想找到要找的,还挺不容易。

马黑黑 发表于 2026-7-14 19:39

红影 发表于 2026-7-14 19:29
想找到要找的,还挺不容易。

对。即便是肉眼可见的匹配,在变成世界,它依然是复杂的

红影 发表于 2026-7-14 20:42

马黑黑 发表于 2026-7-14 19:39
对。即便是肉眼可见的匹配,在变成世界,它依然是复杂的

是的,就像机器人,即使很很简单的动作,实现也是很难的。

马黑黑 发表于 2026-7-14 20:58

红影 发表于 2026-7-14 20:42
是的,就像机器人,即使很很简单的动作,实现也是很难的。

嗯嗯,大约如此

红影 发表于 2026-7-14 21:51

马黑黑 发表于 2026-7-14 20:58
嗯嗯,大约如此

所以学起来也不容易。

马黑黑 发表于 2026-7-15 18:05

红影 发表于 2026-7-14 21:51
所以学起来也不容易。

不易也不难

红影 发表于 2026-7-17 17:46

马黑黑 发表于 2026-7-15 18:05
不易也不难

嗯嗯,对认真的人不难{:4_173:}

马黑黑 发表于 2026-7-17 21:50

红影 发表于 2026-7-17 17:46
嗯嗯,对认真的人不难

嗯嗯,难就难在认真二字而已
页: [1] 2 3
查看完整版本: textarea模拟高亮关键字