网站首页 » 前端开发 » Vue » Vue2 Element calcTextareaHeight.js 详解
上一篇:
下一篇:

Vue2 Element calcTextareaHeight.js 详解

前言

这是在模仿 input 的 textarea 的时候遇到的一个文件,这个文件主要的作用就是实现 textarea 的高度可自适应的功能,代码量不多,但也有必要解释下里面的代码是什么意思。下面直接把代码贴出来。代码中含有注释。

calcTextareaHeight.js 深入浅出

calcTextareaHeight.js
let hiddenTextarea;
// 预置一些样式,供后面直接使用
const HIDDEN_STYLE = `
  height:0 !important;
  visibility:hidden !important;
  overflow:hidden !important;
  position:absolute !important;
  z-index:-1000 !important;
  top:0 !important;
  right:0 !important
`;

// 预订好要从一堆样式中取出来以下样式。
const 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'
];

function calculateNodeStyling(targetElement) {
  // 获取元素的所有相关样式(包括继承的)
  const style = window.getComputedStyle(targetElement);

  // getPropertyValue 为 style 原型链上的一个方法,还有其它方法比如:setProperty()、removeProperty 等等,你可以自己打印这个对象出来看看
  const boxSizing = style.getPropertyValue('box-sizing');

  // 计算下目标元素的上下内边距
  const paddingSize = (
    parseFloat(style.getPropertyValue('padding-bottom')) +
    parseFloat(style.getPropertyValue('padding-top'))
  );

  // 计算下目标元素的上下边框宽度
  const borderSize = (
    parseFloat(style.getPropertyValue('border-bottom-width')) +
    parseFloat(style.getPropertyValue('border-top-width'))
  );

  // 把上面预设好的样式从 style 中取出值,并用分号把这些样式拼成一个字符串
  const contextStyle = CONTEXT_STYLE
    .map(name => `${name}:${style.getPropertyValue(name)}`)
    .join(';');

  // 返回一个对象
  return { contextStyle, paddingSize, borderSize, boxSizing };
}

export default function calcTextareaHeight(
  targetElement,
  minRows = 1,
  maxRows = null
) {
  // 如果不存在 hiddenTextarea ,创建一个 textarea 元素,并添加到页面中。
  if (!hiddenTextarea) {
    hiddenTextarea = document.createElement('textarea');
    document.body.appendChild(hiddenTextarea);
  }

  // 这里是 ES6 的解构赋值,从 calculateNodeStyling 方法返回的对象中取出以下值
  let {
    paddingSize,
    borderSize,
    boxSizing,
    contextStyle
  } = calculateNodeStyling(targetElement);

  // 给创建的 textarea 元素添加行间样式,
  // ${} 这个也是 ES6 中用于在 `` 中解析变量的操作符,
  // `` 也是 ES6 中的跟单引号和双引号的作用差不多,只不过它支持换行以及可以在它里面写变量。
  hiddenTextarea.setAttribute('style', `${contextStyle};${HIDDEN_STYLE}`);
  // 设置 hiddenTextarea 的值,首先目标元素的值,其次为目标元素的 placeholder,最后都不存在,则为空
  hiddenTextarea.value = targetElement.value || targetElement.placeholder || '';

  // scrollHeight 这个只读属性是一个元素内容高度的度量,包括由于溢出导致的视图中不可见内容。
  // 没有垂直滚动条的情况下,scrollHeight 值与元素视图填充所有内容所需要的最小值 clientHeight 相同。
  // 包括元素的 padding,但不包括元素的 border 和 margin。scrollHeight 也包括 ::before 和 ::after这样的伪元素。
  let height = hiddenTextarea.scrollHeight;
  const result = {};

  // border-box:包括内边距和边框的盒子
  // content-box:不包括内边距和边框的盒子
  // 如果 boxSizing 的属性值为 border-box ,则 height 的则为需加上下边框的大小
  // 否则如果为 content-box 则减去上下 padding 的大小
  if (boxSizing === 'border-box') {
    height = height + borderSize;
  } else if (boxSizing === 'content-box') {
    height = height - paddingSize;
  }

  hiddenTextarea.value = '';

  // hiddenTextarea 单文字的高度
  let singleRowHeight = hiddenTextarea.scrollHeight - paddingSize;

  // 如果 minRows 存在
  if (minRows !== null) {
    // 计算出最少行时的高度
    let minHeight = singleRowHeight * minRows;
    // 如果目标元素设置了 border-box ,那么还得加上上下边距的大小和上下边框的大小
    if (boxSizing === 'border-box') {
      minHeight = minHeight + paddingSize + borderSize;
    }

    // 在最小值与heigth 中求出最大值
    height = Math.max(minHeight, height);
    result.minHeight = `${ minHeight }px`;
  }
  // 如果存在 maxRows
  if (maxRows !== null) {
    // 计算出最多行数的总高度
    let maxHeight = singleRowHeight * maxRows;
    if (boxSizing === 'border-box') {
      maxHeight = maxHeight + paddingSize + borderSize;
    }
    // 在最大值与 heigth 中求出最小值
    height = Math.min(maxHeight, height);
  }
  result.height = `${ height }px`;
// 该算的值都算完后,就把 hiddenTextarea 删掉。
  hiddenTextarea.parentNode && hiddenTextarea.parentNode.removeChild(hiddenTextarea);
  hiddenTextarea = null;
  return result;
};

最后直接返回了一个对象,这个对象含有两个属性,一个是 minHeight 另一个是 height。

相关阅读

《ES6 标准入门》学习笔记(第三章:变量的解构赋值)

 

  • 微信扫一扫,赏我

  • 支付宝扫一扫,赏我

声明

原创文章,不经本站同意,不得以任何形式转载,如有不便,请多多包涵!

本文永久链接:http://yunkus.com/vue-element-calctextareaheight/

发表评论

电子邮件地址不会被公开。 必填项已用*标注

评论 END