auto-height仅在H5和微信小程序中直接生效,支付宝等小程序需手动计算高度;须设width:100%和box-sizing:border-box,用uni.createSelectorQuery()查真实高度并防抖,绑定style控制max-height和overflow。

uni-app 中 auto-height 属性能直接用,但有平台限制
在 H5 和微信小程序中,auto-height 是最简方案,设为 true 即可让 textarea 随内容撑开。但支付宝小程序、字节跳动小程序等不支持该属性,会退化为固定高度——此时必须手动计算。
常见错误现象:auto-height 在真机调试时没反应,或 iOS 微信里高度卡住不动。原因多是父容器未设置 width: 100% 或遗漏了 box-sizing: border-box,导致内部尺寸计算错乱。
- 务必给
textarea设置width: 100%(尤其在 flex 布局中) - 加上
box-sizing: border-box,否则 padding 和 border 会额外增加高度 - H5 端可配合
resize: none隐藏拖拽手柄;小程序端无效,无需加
手动计算高度必须用 uni.createSelectorQuery(),不能用 ref
很多人试图用 this.$refs.textarea 拿 DOM 元素再读 scrollHeight,这在小程序里根本不可行——ref 拿到的是组件实例,不是真实节点,scrollHeight 为 undefined。
正确做法是通过节点查询 API 获取布局信息:
onInput() {
const query = uni.createSelectorQuery().in(this);
query.select('textarea').boundingClientRect(data => {
if (data) {
// data.height 是当前渲染出的视觉高度(含 padding)
this.textareaHeight = Math.max(40, data.height);
}
}).exec();
}
注意点:
- 必须用
.in(this)绑定当前组件作用域,否则查不到 -
boundingClientRect返回的是渲染后的真实高度,比靠行数估算更准 - 不要在
input回调里立即查——内容可能还没重绘,加setTimeout(..., 0)更稳妥
最大高度限制要靠 :style 绑定 max-height,不能只靠 CSS 类
仅在样式表里写 max-height: 200px 是无效的:当 auto-height 开启时,它会忽略这个限制;而手动绑定高度时,CSS 类里的 max-height 又可能被内联 height 覆盖优先级。
必须显式绑定:
<textarea :style="{ height: textareaHeight + 'px', 'max-height': '200px', overflow: 'auto' }"></textarea>
关键细节:
-
overflow: auto必须写,否则超出部分不可滚动 - 如果同时用
auto-height和:style,部分平台(如旧版微信)会冲突,建议二选一 - 真机上
max-height生效的前提是父容器没有overflow: hidden,否则滚动条被裁掉
防抖和最小高度是上线前最容易漏的两个点
用户狂敲键盘时,@input 每次都触发高度计算,频繁调用 createSelectorQuery 会导致卡顿,尤其低端安卓机。这不是理论风险,是实测会发生的性能问题。
最小高度也常被忽略:空内容时 boundingClientRect 返回的高度可能小于字体行高,导致 textarea “塌陷”成一条线。
- 用
lodash.debounce或简单计时器防抖,延迟 100ms 再查高度 - 初始
textareaHeight至少设为40(对应 1 行 + padding),并用Math.max(40, data.height)保底 - 测试时务必在微信、支付宝、H5 三端各输 1 字、10 字、50 字、带换行符的内容,观察是否跳变或截断
真正麻烦的从来不是“怎么让它变高”,而是“怎么让它不变形、不卡、不溢出、不塌”。这几个点没压住,上线后就会收一堆“输入框不见了”“打字卡顿”的反馈。











