本篇文章小编给大家分享一下Vue中textarea自适应高度方案代码实现方法,文章代码介绍的很详细,小编觉得挺不错的,现在分享给大家供大家参考,有需要的小伙伴们可以来看看。
隐藏的问题
抛开原生JS,框架的大部分UI库都支持自适应textarea高度功能,但普遍都忽略了一个功能,就是自适应高度的回显。
使用这些库的时候,我们很容易的在textarea中键入内容,超出范围时会自动延展一行,保证内容高度的自适应。当我们提交内容,在其它页面使用同样的UI来渲染时,麻烦的就来了,有些UI库是不支持自适应回显的,这就需要我们通过行高、行数甚至高度之间的计算得出一个基值,从而实现回显。
解决自适应高度的方案
常见得方案有两种,一种是在页面地“边远地区”添加一个ghost dom来模拟输入换行,这个dom的可能是editable属性为true的div或者是一个一摸一样得textarea。
以element-ui的input组件举例,当我们在组件内输入值时,会调用resizeTextarea方法
resizeTextarea() { if (this.$isServer) return; const { autosize, type } = this; if (type !== 'textarea') return; if (!autosize) { this.textareaCalcStyle = { minHeight: calcTextareaHeight(this.$refs.textarea).minHeight }; return; } const minRows = autosize.minRows; const maxRows = autosize.maxRows; this.textareaCalcStyle = calcTextareaHeight(this.$refs.textarea, minRows, maxRows); }
当设置了autosize为true则textarea设为自适应高度。此时textarea的高度会通过calcTextareaHeight方法实时计算。
export default function calcTextareaHeight( targetElement, minRows = 1, maxRows = null ) { if (!hiddenTextarea) { hiddenTextarea = document.createElement('textarea'); document.body.appendChild(hiddenTextarea); } let { paddingSize, borderSize, boxSizing, contextStyle } = calculateNodeStyling(targetElement); hiddenTextarea.setAttribute('style', `${contextStyle};${HIDDEN_STYLE}`); hiddenTextarea.value = targetElement.value || targetElement.placeholder || ''; let height = hiddenTextarea.scrollHeight; const result = {}; if (boxSizing === 'border-box') { height = height + borderSize; } else if (boxSizing === 'content-box') { height = height - paddingSize; } hiddenTextarea.value = ''; let singleRowHeight = hiddenTextarea.scrollHeight - paddingSize; if (minRows !== null) { let minHeight = singleRowHeight * minRows; if (boxSizing === 'border-box') { minHeight = minHeight + paddingSize + borderSize; } height = Math.max(minHeight, height); result.minHeight = `${ minHeight }px`; } if (maxRows !== null) { let maxHeight = singleRowHeight * maxRows; if (boxSizing === 'border-box') { maxHeight = maxHeight + paddingSize + borderSize; } height = Math.min(maxHeight, height); } result.height = `${ height }px`; hiddenTextarea.parentNode && hiddenTextarea.parentNode.removeChild(hiddenTextarea); hiddenTextarea = null; return result; };
我们可以看到
if (!hiddenTextarea) { hiddenTextarea = document.createElement('textarea'); document.body.appendChild(hiddenTextarea); }
element-ui创建了一个textarea的dom,通过calculateNodeStyling方法将真正的textarea的样式复制给hiddenTextarea(overflow不同步,真正的textarea是为hidden)。接着监听textarea的输入值,同步给hiddenTextarea。同时将hiddenTextarea的scrollHeight同步给textarea的高度,最后再将dom销毁掉。
关于样式的同步,element这里用了getComputedStyle和getPropertyValue这两个API。当然,如果你自己封装的话,也可以使用css预处理器的mixin。
第二种方案与第一种方案类似,不过不会创建额外的dom。以开头的vue-awesome-textarea举例:
init() { this.initAutoResize() }, initAutoResize () { this.autoResize && this.$nextTick(this.calcResize) }
在页面mounted或者内容变动且开启自适应高度autoResize的时候,执行this.calcResize方法。
calcResize() { this.resetHeight() this.calcTextareaH() }, resetHeight() { this. }, calcTextareaH() { let contentHeight = this.calcContentHeight() this.px' if (this.needUpdateRows(contentHeight)) { this.updateRows(contentHeight) } this.oldContentHeight = contentHeight }, calcContentHeight () { const { paddingSize } = this.calcNodeStyle(this.$el) return this.$el.scrollHeight - paddingSize },
resetHeight()是来初始化textarea的高度,默认为auto。calcTextareaH()方法是用来计算内容区域的高度(textarea的scrollHeight减去padding的高度),同时将计算好的高度实时同步给textarea的高:
this.px'
相比方案一,这个方案采用的思路相同(动态修改高度),但是减少了额外的dom创建和销毁的过程。
此外,vue-awesome-textarea还支持在自适应的过程中回调行数,可以更好的支持数据回显。实现的方法也很简单:
computed: { ... oneRowsHeight() { return this.calcContentHeight() / Number(this.rows) || 0 } ... }
在computed中我们计算出单行的高度,同时在执行this.calcTextareaH()方法时我们记录下内容高度:
this.oldContentHeight = contentHeight
接着我们会比对是否存在添加行操作,一旦添加则新的内容高度和老的内容高度会不同:
needUpdateRows(newContentHeight) { return this.oldContentHeight !== newContentHeight },
此时我们会把最新的行高emit到组件外部:
updateRows(contentHeight) { this.$emit('getRows', Math.round(contentHeight / this.oneRowsHeight)) }
忍者必须死34399账号登录版 最新版v1.0.138v2.0.72
下载勇者秘境oppo版 安卓版v1.0.5
下载忍者必须死3一加版 最新版v1.0.138v2.0.72
下载绝世仙王官方正版 最新安卓版v1.0.49
下载Goat Simulator 3手机版 安卓版v1.0.8.2
Goat Simulator 3手机版是一个非常有趣的模拟游
Goat Simulator 3国际服 安卓版v1.0.8.2
Goat Simulator 3国际版是一个非常有趣的山羊模
烟花燃放模拟器中文版 2025最新版v1.0
烟花燃放模拟器是款仿真的烟花绽放模拟器类型单机小游戏,全方位
我的世界动漫世界 手机版v友y整合
我的世界动漫世界模组整合包是一款加入了动漫元素的素材整合包,
我的世界贝爷生存整合包 最新版v隔壁老王
我的世界MITE贝爷生存整合包是一款根据原版MC制作的魔改整