当前位置: 首页 > Web前端 > HTML5

textarea的autoHeight函数怎么实现

时间:2023-04-05 19:53:30 HTML5

这个函数比较常用,用来获取文字的长宽(避免计算不准的问题),主要用来实现textarea的自动加长。可以看出,我们在使用textarea的时候,有时候需要感知内容的高度,然后动态展开。(elementUI的textarea提供了autosize的功能。)那么我们要实现这样的功能应该怎么做呢?获取内容,并计算字符数估计值。中文算二,英文算一。但是仍然存在问题,例如非等宽字体。精明的读者已经看到,我们中间的div效果就是我们想要的高度。也是elementUI的解决方法,创建一个相同样式的div,然后获取它的高度。构建具有相同样式的DOM似乎是最佳解决方案。那么如何构建相同的DOM呢?由于我们要构建相同的DOM,因此我们需要知道DOM的外观。那么如何获得样式呢?上课?获得风格?nonono,我们需要使用window.getComputedStyle(el),然后我们就可以愉快的拿到计算出来的属性了。然后我们需要知道哪些属性会影响字体对齐。CONTEXT_STYLE=['letter-spacing','line-height','padding-top','padding-bottom','font-family','font-weight','font-size','text-rendering','text-transform','width','text-indent','padding-left','padding-right','border-width','box-sizing']因为我们需要重新创建一个DOM节点,而我们不想让这个过程被用户看到,所以我们要隐藏它。计划是什么?display:none这个是不行的,因为none之后就不会画了。你无法获得宽度和高度。opacity:0可以是visibility:hidden;这个也可以height:0;overflow:hidden也可以得到,scrollHeightz-index:-999也可以得到。position:absolute;top:-9999px;left:-9999px也是可以的elementUI实现https://github.com/ElemeFE/element/blob/dev/packages/input/src/calcTextareaHeight.jslethiddenTextarea;constHIDDEN_STYLE=`height:0重要;可见性:隐藏!重要;溢出:隐藏!重要;位置:绝对!重要;z-index:-1000!important;顶部:0!重要;right:0!important`;constCONTEXT_STYLE=['letter-spacing','line-height','padding-top','padding-bottom','font-family','font-weight','font-size','text-rendering','text-transform','width','text-indent','padding-left','padding-right','border-width','box-sizing'];函数calculateNodeStyling(targetElement){conststyle=window.getComputedStyle(targetElement);constboxSizing=style.getPropertyValue('box-sizing');constpaddingSize=(parseFloat(style.getPropertyValue('padding-bottom'))+parseFloat(style.getPropertyValue('padding-top')));constborderSize=(parseFloat(style.getPropertyValue('border-bottom-width'))+parseFloat(style.getPropertyValue('border-top-width')));constcontextStyle=CONTEXT_STYLE.map(name=>`${name}:${style.getPropertyValue(name)}`).join(';');return{contextStyle,paddingSize,borderSize,boxSizing};}导出默认函数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.占位符||'';letheight=hiddenTextarea.scrollHeight;常量结果={};if(boxSizing==='border-box'){height=height+borderSize;}elseif(boxSizing==='content-box'){h八=高度-paddingSize;}hiddenTextarea.value='';让singleRowHeight=hiddenTextarea.scrollHeight-paddingSize;if(minRows!==null){让minHeight=singleRowHeight*minRows;if(boxSizing==='border-box'){minHeight=minHeight+paddingSize+borderSize;}height=Math.max(minHeight,height);result.minHeight=`${minHeight}px`;}if(maxRows!==null){让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);隐藏文本区域=空;返回结果;};微信公众号:前端linong