如何在MUI TextField组件中实现行号显示功能
用MUI TextField实现带行号的代码编辑器
可以通过MUI TextField组件实现带行号的代码编辑器,你的核心问题在于行号区域与输入框的样式未统一,以及状态更新逻辑错误导致行号和内容无法对齐。下面是修正后的实现方案:
原代码的主要问题
useLineText钩子返回的updateNewLine方法未被调用,直接用setCountLineText传递行数是无效的,导致行号无法正确更新。- 行号的
<p>标签与TextField的行高、字体、内边距不一致,自然无法对齐。 - 状态更新存在异步问题,修改
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
相关产品推荐
相关产品推荐

