element性能优化之实时计算textarea高度
el-input
中有个属性
autosize
加上后,
textarea
的高度会随着内容高度被撑开,而不是默认的那样会出现滚动条:
<el-input
type="textarea"
autosize
placeholder="请输入内容"
v-model="textarea">
</el-input>
- 不加 autosize时,内容撑了会出现滚动条
- 加了 autosize时,高度会随着内容撑开
原理
监听了 textarea的val的变化,通过实时创建一个内容跟原来textarea一样,但是隐藏的textarea元素,计算出该隐藏的textarea的高度,然后赋值给真正的textarea,这样就做了性能优化,减少了页面的重绘
核心代码如下:我加了一些自己的注解
export default function calcTextareaHeight(
targetElement,
minRows = 1,
maxRows = null
) {
debugger
if (!hiddenTextarea) {
hiddenTextarea = document.createElement('textarea'); // 创建一个隐藏的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; // 实际内容尺寸 + padding
const result = {};
if (boxSizing === 'border-box') { // 那么 height = 内容区高度(被压缩过) + padding
height = height + borderSize; // 实际占的屏幕的高度 实际内容尺寸 + padding + border
// 这里要加上 borderSize 是因为
// 如果是 border-box的话,那么设置高度时,实际上设置的是整个占屏高度,
// 而这里得到的 scrollHeight是 实际内容尺寸 + padding,,,所有在设置最终高度时吗,要把border加上
// 内容区需要 减去 padidng 和 borderSize
} else if (boxSizing === 'content-box') { // 那么 height = 内容区高度(未被压缩过) + padding
height = height - paddingSize; // 实际内容区的高度 实际内容尺寸 + padding - padding = 实际内容高度
// 这里减去paddigSize是因为 这个height是要被拿到textarea中去进行设置的,那么设置了textare的高度
// 如果是 content-box是话,那么设置的 height 就是内容区的高度,实际占屏高度是 要加上 padding + border的
// 所以这里只需要获取到纯纯的内容区高度就行了
}
// 结论就是: border-box设置的高度就是占屏高度, 设置时,要加上border
// ,,而content-box设置的高度,这是内容区的纯纯的高度,不能包括pading + border,,设置时只需要纯纯的高度
hiddenTextarea.value = '';
let singleRowHeight = hiddenTextarea.scrollHeight - paddingSize; // 单行 内容区纯高度 实际内容尺寸 + padding = padding = 实际内容尺寸
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;
};
涉及到的其他知识点:
版权声明:本文为github_36091081原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。