input組件相對來說復雜一點,我們先從它用到的一個工具庫calcTextareaHeight.js進行分析。
calcTextareaHeight.js
calcTextareaHeight.js使用來計算文本框的高度的,我們根據代碼順序從上往下進行分析。
HIDDEN_STYLE
HIDDEN_STYLE是一個常量,存儲隱藏時候的css樣式的。
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`;
CONTEXT_STYLE
CONTEXT_STYLE也是一個常量,用來存儲要查詢的樣式名。
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'];
calculateNodeStyling
calculateNodeStyling用來獲取結點的某些樣式。
function calculateNodeStyling(node) { const style = window.getComputedStyle(node); // 獲取結點的計算后的樣式,即實際渲染的樣式 const boxSizing = style.getPropertyValue('box-sizing'); // 獲取 box-sizing 的值 // 上下的 padding 之和 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')) ); // 其他一些樣式 const contextStyle = CONTEXT_STYLE .map(name => `${name}:${style.getPropertyValue(name)}`) .join(';'); return { contextStyle, paddingSize, borderSize, boxSizing };}calcTextareaHeight
calcTextareaHeight是最終暴露出去的函數,用來計算文本域的高度。
export default function calcTextareaHeight( targetNode, // 要計算的結點 minRows = null, // 最小的行數 maxRows = null // 最大的行數) { if (!hiddenTextarea) { // 來創建一個隱藏的文本域,所有的計算都是在這上面進行的 hiddenTextarea = document.createElement('textarea'); document.body.appendChild(hiddenTextarea); } // 獲取結點一些樣式值 let { paddingSize, borderSize, boxSizing, contextStyle } = calculateNodeStyling(targetNode); // 設置相應的樣式 hiddenTextarea.setAttribute('style', `${contextStyle};${HIDDEN_STYLE}`); // 設置內容,按優先級一次是 結點的 value, 結點的 placeholder, 以及空字符串 hiddenTextarea.value = targetNode.value || targetNode.placeholder || ''; // 獲取滾動高度 let height = hiddenTextarea.scrollHeight; if (boxSizing === 'border-box') { // 如果是 border-box,說明高度得加上邊框 height = height + borderSize; } else if (boxSizing === 'content-box') { // 如果是 content-box,說明得減去上下內邊距 height = height - paddingSize; } // 計算單行高度,先清空內容 hiddenTextarea.value = ''; // 再用滾動高度減去上下內邊距 let singleRowHeight = hiddenTextarea.scrollHeight - paddingSize; if (minRows !== null) { // 如果參數傳遞了 minRows let minHeight = singleRowHeight * minRows; // 說明最少應當有這么多行的高度 if (boxSizing === 'border-box') { // 如果是 border-box,還得加上上下內邊距和上下邊框的寬度 minHeight = minHeight + paddingSize + borderSize; } height = Math.max(minHeight, height); // 取二者最大值 } if (maxRows !== null) { // 如果參數傳遞了 maxRows let maxHeight = singleRowHeight * maxRows; // 說明最多只能有這么多行的高度 if (boxSizing === 'border-box') { // 如果是 border-box,還得加上上下內邊距和上下邊框的寬度 maxHeight = maxHeight + paddingSize + borderSize; } height = Math.min(maxHeight, height); // 取二者最小值 } // 返回文本域應當設置的高度 return { height: height + 'px'};};
新聞熱點
疑難解答
圖片精選