React中如何根据textarea输入内容动态调整rows属性值
实现方案
你可以通过两种方式实现需求,可根据你的兼容要求选择:
方案1:全浏览器兼容JS实现(推荐)
通过监听输入事件结合DOM属性计算实际行数,动态调整textarea高度,最少2行,最多8行,超出自动出滚动条:
- 组件逻辑代码(React):
import { useState, useRef, useEffect } from 'react'; function YourComponent() { const [something, setSomething] = useState(''); const textareaRef = useRef(null); const handleInput = (e) => { const textarea = e.target; // 先重置为最小行数,保证删除内容时高度可以回缩 textarea.rows = 2; // 获取样式属性计算行数 const computedStyle = getComputedStyle(textarea); const lineHeight = parseInt(computedStyle.lineHeight); const paddingTop = parseInt(computedStyle.paddingTop); const paddingBottom = parseInt(computedStyle.paddingBottom); // 计算内容实际高度对应的行数 const contentHeight = textarea.scrollHeight - paddingTop - paddingBottom; const currentRows = Math.round(contentHeight / lineHeight); // 限制行数范围:最少2行,最多8行 textarea.rows = Math.min(Math.max(currentRows, 2), 8); setSomething(e.target.value); }; // 处理初始有默认值的场景,组件挂载/默认值变化时自动计算高度 useEffect(() => { if (textareaRef.current) { textareaRef.current.dispatchEvent(new Event('input')); } }, [something]); return ( <textarea ref={textareaRef} rows={2} onChange={handleInput} className='form-control text-area' value={something} placeholder='write something' /> ) }
- 配套CSS样式:
.text-area { /* 固定行高避免计算误差,可根据需求调整数值 */ line-height: 1.5rem; /* 上下内边距,可根据需求调整数值 */ padding: 0.5rem 0.75rem; /* 最大高度 = 8行 * 行高 + 上下内边距,对应上面的数值计算:8*1.5 + 0.5*2 = 13rem */ max-height: 13rem; overflow-y: auto; /* 如需允许用户手动拖拽调整大小可删除下行 */ resize: none; }
该方案兼容所有主流浏览器,同时能正确处理手动输入换行、文本过长自动折行两种场景的行数计算。
方案2:纯CSS极简实现(无需JS)
如果你不需要兼容2024年之前的旧版本浏览器,可以使用新CSS属性field-sizing实现,无需写任何JS逻辑:
.text-area { field-sizing: content; /* 最小高度对应2行,数值可根据你的行高、内边距调整 */ min-height: calc(2 * 1.5rem + 1rem); /* 最大高度对应8行,超出自动出现滚动条 */ max-height: calc(8 * 1.5rem + 1rem); overflow-y: auto; resize: none; }
该方案支持Chrome 123+、Firefox 122+、Safari 17.4+版本浏览器。
内容的提问来源于stack exchange,提问作者HiddenHopes
相关产品推荐
相关产品推荐

