可適應文本高度的輸入框組件其實一開始是Ant design裏面就有的,Element-ui也實現了,可是經過看源碼,其實用的都是一個類似的js...node
咱們須要實現的這個組件,能夠指定最小行數(minRows
)和最大行數(maxRows
),用來限定textarea的高度變化範圍。ui
可自適應文本高度的輸入框spa
說一下具體的實現思路吧.net
minRows * singleRowHeight
與 maxRows *singleRowHeight
,這樣就有了一個最大、最小高度範圍。height, minHeight, maxHeight
.作一下範圍判斷,就能夠得到組件輸入框的實時高度了。具體代碼邏輯:code
// 不可見的節點,用來模擬輸入框,計算當前輸入值所佔的高度 let hiddenTextarea; // 隱藏不可見節點,所使用的樣式 let HIDDEN_STYLE = ` // ... `; // 模擬輸入框,須要考慮模擬哪些樣式 let NODE_STYLE = [ // ... ]; // 計算輸入框的樣式,padding, border, box-sizing, 以及模擬樣式的值 function calcNodeStyle(targetElement) { var styles = window.getComputedStyle(targetElement); // ... return {nodeStyle,paddingSize,borderSize,boxSizing}; } function calcTextareaHeight(targetElement, minRows=1, maxRows=null) { // ... // 增長不可見節點,模擬組件輸入框的樣式 hiddenTextarea.setAttribute('style', `${nodeStyle};${HIDDEN_STYLE}`); // 計算出單行文本的高度 hiddenTextarea.value = ''; let singleRowHeight = hiddenTextarea.scrollHeight - paddingSize; // 計算當前輸入值所佔高度 hiddenTextarea.value = targetElement.value || targetElement.placeHolder; let height = hiddenTextarea.scrollHeight; // ... let result = {}; if(minRows) { // 根據單行文本高度,計算最小高度值 } if(maxRows) { // 根據單行文本高度,計算最大高度值 } result.height = `${height}px`; hiddenTextarea.parentNode && hiddenTextarea.parentNode.removeChild(hiddenTextarea); hiddenTextarea = null; return result; }
看一下MDN中對於scrollHeight的定義:Element.scrollHeightblog
從下圖中,咱們能夠很直觀的看出,scrollHeight = 內容區域高度(content-height) + paddingSize
。不包括border以及margin的值。ip
在這個組件中,咱們須要去模擬當前輸入框的樣式,去計算當前輸入值會佔多少的高度,就須要用到這個屬性。ci
let HIDDEN_STYLE = ` height:0 !important; overflow:hidden !important; position: fixed !important; top: -9999px !important; left: -9999px !important; opacity: 0 !important; `; function calcTextareaHeight(targetElement, minRows=1, maxRows=null) { // ... hiddenTextarea.value = ''; let singleRowHeight = hiddenTextarea.scrollHeight - paddingSize; hiddenTextarea.value = targetElement.value || targetElement.placeHolder; let height = hiddenTextarea.scrollHeight; if(boxSizing === 'border-box') { height = height + borderSize; } else if(boxSizing === 'content-box') { height = height - paddingSize; } }
注意HIDDEN_STYLE中,height: 0;
這個很是重要。由於不這麼作的話,你取到的scrollHeight的值是組件輸入框的高度,而不是他輸入值文本所佔的高度。rem
還有一點須要提下,仔細看HIDDEN_STYLE
的屬性,咱們都是經過visible, top, right, opacity來隱藏這個節點,而沒有使用display:none; 由於,設置dispaly:none後,就沒有這個節點了, scrollHeight是獲取不到值的!!!get
只要明白了實現的思路,其實後面就好寫了。關鍵點仍是在於對於box-sizing,以及模擬樣式的健壯性考慮。
經過這個組件: