element性能优化之实时计算textarea高度

  • Post author:
  • Post category:其他




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 版权协议,转载请附上原文出处链接和本声明。