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

如何在编辑器中高亮光标所在行的行号

解决编号div中高亮当前活动行的问题

你遇到的问题是能获取textarea的当前行号,但无法正确给编号div对应的行添加背景高亮,核心原因是事件覆盖不全、未清除历史高亮、边界场景处理缺失,以下是修复方案:

修复要点

  • 补充事件监听:仅监听click事件不够,要覆盖键盘移动光标、输入内容、鼠标选中等场景,添加input、keydown、mouseup事件。
  • 清除历史高亮:每次高亮新行前,先把所有行号span的背景色重置,避免多个行同时高亮。
  • 处理边界行号:当光标在最后一行末尾时,行号计算会超出数组索引,需要修正行号值。
  • 行号更新后同步高亮:更新行号列表后,重新高亮当前行,保证行号变化后高亮状态不丢失。

完整代码

HTML

<body>
<div class="editor">
  <div class="numbers">
   <span></span>
  </div>
<textarea wrap="off" id="textarea" rows="10" cols="50" onkeyup="updateRowNumbering(this)"></textarea>
</div>
</body>

CSS

body,
textarea {
  font-family: Consolas, "Courier New", Courier, monospace;
}

.editor {
  display: inline-grid;
  grid-template-columns: 3em auto;
  gap: 10px;
  line-height: 21px;
  background: rgb(40 42 58);
  border-radius: 2px;
  overflow-y: auto;
  max-height: 243px;
}

.editor>* {
  padding-top: 10px;
  padding-bottom: 10px;
}

.numbers {
  text-align: right;
  background: #333;
  padding-right: 5px;
}

.numbers span {
  counter-increment: linenumber;
}

.numbers span::before {
  content: counter(linenumber);
  display: block;
  color: #888;
}

textarea {
  line-height: 21px;
  border: 0;
  background: transparent;
  color: #fff;
  min-width: 500px;
  outline: none;
  resize: none;
  padding-right: 10px;
}

JavaScript

const ta = document.querySelector('textarea')

function updateRowNumbering() {
  const num = ta.value.split("\n").length;
  const numbers = ta.parentNode.querySelector(".numbers");
  numbers.innerHTML = Array(num).fill(`<span style="overflow: hidden"></span>`).join("");
  // 行号更新后重新高亮当前行
  highlightLineNumber(getCurrentLineNumber());
}

ta.textContent = `I love
Tanzania
Nasila
America
Football
JavaScript
Chess
Ang Probinsyano
Startimes
China`

updateRowNumbering();

function getCurrentLineNumber() {
  const caretPosition = ta.selectionStart;
  const text = ta.value;
  const lines = text.split('\n');
  let currentLine = 1;
  let accumulatedLength = 0;

  for (let i = 0; i < lines.length; i++) {
    accumulatedLength += lines[i].length + 1; // +1 是换行符的长度
    if (caretPosition < accumulatedLength) {
      currentLine = i + 1;
      break;
    }
    // 处理光标在最后一行末尾的情况
    if (i === lines.length - 1 && caretPosition === accumulatedLength - 1) {
      currentLine = i + 1;
    }
  }
  return currentLine;
}

function highlightLineNumber(lineNumber) {
  const numberSpans = document.querySelectorAll('.numbers span');
  // 清除所有高亮
  numberSpans.forEach(span => {
    span.style.backgroundColor = '';
  });
  // 高亮当前行,避免索引越界
  if (lineNumber > 0 && lineNumber <= numberSpans.length) {
    numberSpans[lineNumber - 1].style.backgroundColor = 'gray';
  }
}

// 绑定所有需要监听的事件
const textarea = document.querySelector('#textarea');
['click', 'input', 'keydown', 'mouseup'].forEach(event => {
  textarea.addEventListener(event, () => {
    const currentLine = getCurrentLineNumber();
    highlightLineNumber(currentLine);
  });
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 14:44:53