在開發IM的項目過程當中,常常會有出現一些須要計算DOM高度,而後超出若干行隱藏等需求。不少時候,須要計算高度的DOM元素都是動態生成的,咱們沒法在數據渲染前獲取到它的高度。javascript
若是沒有任何交互,咱們能夠經過CSS來實現這個需求。可是,若是咱們須要使用JavaScript來實現一些交互(好比消息渲染時,超過2行顯示某個特定按鈕等),則只能經過JavaScript來進行實現。我在這裏介紹一種經過JavaScript來對元素高度進行計算的方法,但願可以給你們提供一些思路。html
根據前端的基本常識,在內存中未渲染的DOM元素是沒法獲取到高度的,所以咱們有兩個方向來解決這個難題:前端
如下的實現方案將根據上面所選擇的技術方案來進行實現。java
此方案無需多言,就是經過字的總數、行高和每一行可以容下的字的個數進行估算等。在項目最開始時,我採用的就是這個方案。具體實現代碼較爲簡單,所以不在本文中提供示例。node
此方案實現簡單,基本不須要任何技術成本。算法
只適用於等寬文字,若是出現富文本(好比有emoji或者圖片表情等高度不一致)的狀況,則沒法適用。若是字體爲非等寬字體或者存在\n
之類的換行符或者是\t
之類的製表符時,估算的準確度也會降低。瀏覽器
顧名思義,此方案就是先不考慮DOM元素行數邏輯,直接將全部的DOM節點所有渲染到頁面中,渲染完成後再對進行後續邏輯判斷。獲取高度後頁面行數計算將在後面統一講解。app
此方案經過直接在實際場景的頁面上渲染後進行高度計算,所以計算精準,不存在任何誤差。同時,此方案實現起來也較爲簡單,只須要將業務邏輯執行時間後延,並不須要開發額外的代碼。佈局
該方案缺點也比較明顯,因爲是先渲染後處理,所以頁面DOM元素會出現重繪和重排,致使頁面閃動,從而影響用戶的體驗。字體
該方案的靈感來自於上一個方案。由於在實際的頁面中進行計算可以保證頁面高度計算沒有任何偏差,所以咱們須要一個實際的場景,讓瀏覽器來幫助咱們進行高度計算。同時,咱們又不能在具體的功能頁面中先渲染後計算,所以咱們能夠直接建立一個與實際頁面中如出一轍的容器來進行高度計算。這樣咱們既可以精確計算,又可以不影響用戶體驗。
具體實現的代碼能夠參考以下示例:
export default function getLines(element = 'div', style = {}, html = '') {
let node = document.createElement(element);//建立一個新容器
let length;
each(style, (element, index) => {
node.style[index] = element;//將傳入的style遍歷後賦值給新容器
});
node.innerHTML = html;
document.body.appendChild(node);//須要將新容器掛載到DOM中,瀏覽器纔會進行高度計算
let height = global.getComputedStyle(node).height;
document.body.removeChild(node);//須要將鏡像DOM進行移除
if (height.indexOf('px') > 0) {
length = parseInt(height.split('px')[0]);
} else {
length = 0;
}
return length;
}
複製代碼
該方案基本上繼承了第二個方案的全部優勢——精確計算,無偏差,而且避免了出現頁面閃動的狀況。
此方案仍然存在一些問題,將新容器掛載到document元素上時,可能會引起DOM元素的從新渲染,極低機率會影響頁面佈局。同時,屬性值等須要本身手動傳入,而不是利用現成的容器,比較費時費力。
使用cloneNode方法來對現有的容器進行clone,咱們能夠省去輸入樣式的麻煩,同時可以精確保證兩個容器徹底一致。
在實踐過程當中,在append之後馬上remove鏡像DOM節點,不會對頁面產生任何影響。若是擔憂添加時會給頁面形成閃動效果,能夠給鏡像DOM添加上position:fixed;visibility:hidden;z-index:-999;
屬性,可以讓鏡像DOM在append到頁面時,不會影響當前頁面的任何佈局。
爲何咱們不使用display:none
來實現上述效果呢?由於在使用了該屬性後,window.getComputedStyle
獲取的高度將變爲auto
。同理,若是元素的display
屬性爲inline
時,也會出現相似的效果,所以咱們須要將display
指定爲block
或者inline-block
。
理論上咱們的容器都應該爲塊級元素,不然計算高度的意義也就不存在了。所以在容器clone時只須要留意便可,不須要從新指定。
兩個優化點通過實踐已經證實可行,具體代碼就不附上了,若是有須要的能夠給我留言~~
目前,經過高度來計算行數並無什麼比較好的方法,通常是經過line-height
兩個屬性來進行計算。
若是line-height
爲倍數的話,則還須要font-size
屬性來肯定具體高度。
具體算法爲:總高度 / 每一行高度 = 行數
而每一行高度則經過line-height
或者line-height
* font-size
肯定。
獲取動態元素的高度一直都是IM項目中的一個重要需求,本身在這個方面也踩了許多坑,所以寫了這一篇博客來進行記錄,同時其餘人若是看到了也能夠避免一些常見問題。
因爲此方案較爲繁瑣,同時容易留下很多坑,不太推薦使用此方法,仍是建議經過產品方案等其餘手段規避此方案。