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

如何在MUI TextField组件中实现行号显示功能

用MUI TextField实现带行号的代码编辑器

可以通过MUI TextField组件实现带行号的代码编辑器,你的核心问题在于行号区域与输入框的样式未统一,以及状态更新逻辑错误导致行号和内容无法对齐。下面是修正后的实现方案:

原代码的主要问题

  1. useLineText钩子返回的updateNewLine方法未被调用,直接用setCountLineText传递行数是无效的,导致行号无法正确更新。
  2. 行号的<p>标签与TextField的行高、字体、内边距不一致,自然无法对齐。
  3. 状态更新存在异步问题,修改nbLines后立即调用setCountLineText拿到的是旧值。

修正后的完整实现

组件代码

import { useState, useEffect } from 'react';
import { Box, TextField, Typography } from "@mui/material";
import { MainBox, LineNumbersContainer, TextArea } from "./styles";

const CodeInputField = () => {
  const [code, setCode] = useState('');
  const [lineNumbers, setLineNumbers] = useState([1]);

  // 监听代码内容变化,实时生成行号数组
  useEffect(() => {
    const lines = code.split(/\r\n|\r|\n/);
    const numbers = lines.map((_, index) => index + 1);
    setLineNumbers(numbers);
  }, [code]);

  // 同步滚动:输入框滚动时,行号区域跟着滚动
  const handleScroll = (e) => {
    const lineNumbersEl = document.getElementById('line-numbers');
    if (lineNumbersEl) {
      lineNumbersEl.scrollTop = e.target.scrollTop;
    }
  };

  return(
    <Box sx={MainBox}>
      {/* 行号容器 */}
      <Typography component="div" sx={LineNumbersContainer} id="line-numbers">
        {lineNumbers.map(num => (
          <Typography key={num} variant="body1">
            {num}
          </Typography>
        ))}
      </Typography>
      {/* 代码输入框 */}
      <TextField
        sx={TextArea}
        multiline
        value={code}
        onChange={(e) => setCode(e.target.value)}
        onScroll={handleScroll}
        placeholder="输入代码..."
        variant="outlined"
      />
    </Box>
  )
}

export default CodeInputField

样式代码

export const MainBox = () => ({
  display: 'flex',
  border: '1px solid #e0e0e0',
  borderRadius: 2,
  overflow: 'hidden',
  fontSize: '14px', // 统一字体大小
  fontFamily: 'monospace', // 等宽字体适配代码排版
});

export const LineNumbersContainer = () => ({
  backgroundColor: '#f5f5f5',
  padding: '10px 8px',
  textAlign: 'right',
  userSelect: 'none', // 禁止选中行号
  minWidth: '40px',
  overflowY: 'auto',
  '& > *': {
    lineHeight: '20px', // 和输入框行高严格匹配
    margin: 0,
  },
});

export const TextArea = () => ({
  flex: 1,
  borderLeft: '1px solid #e0e0e0',
  '& .MuiOutlinedInput-root': {
    '& fieldset': {
      border: 'none',
    },
    '& .MuiOutlinedInput-input': {
      padding: '10px 12px',
      lineHeight: '20px', // 与行号行高一致
      fontFamily: 'monospace',
      minHeight: '200px',
    },
  },
});

关键优化点

  • 样式统一:行号区域和输入框使用相同的字体、行高、内边距,确保每一行严格对齐。
  • 状态逻辑修复:通过useEffect监听代码内容变化,实时计算行数并生成行号数组,避免异步更新问题。
  • 滚动同步:监听输入框的滚动事件,同步行号区域的滚动位置,确保滚动时行号和内容始终对应。
  • 等宽字体:使用等宽字体(monospace),让代码和行号的排版更整齐,符合代码编辑器的使用习惯。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 04:40:41