如何獲取元素的最終background-color
一、題目
用JS代碼求出頁面上一個(gè)元素的最終的background-color,不考慮IE瀏覽器,不考慮元素float情況。
二、題目解析
1.考察底層JavaScript基礎(chǔ)
前端開發(fā),日常最常接觸的就是頁面樣式的編寫。而擺脫jQuery等工具庫,用原生js獲取樣式,是每個(gè)前端程序猿進(jìn)階階段必須掌握的技能。
2.考察面試者的思維縝密程度和開發(fā)經(jīng)驗(yàn)
如果認(rèn)為單單求元素計(jì)算后的樣式,就有點(diǎn)too young了。頁面的樣式的復(fù)雜,永遠(yuǎn)是最虐心的。就算前端有多牛,一聽到兼容IE6,論誰都會(huì)心塞??。所以還要考慮特殊的情況:display,opacity,visibility的取值。
三、理論基礎(chǔ)
1. 內(nèi)聯(lián)樣式
內(nèi)聯(lián)樣式可以通過元素的style屬性獲取,如果style屬性有background-color值,則可以直接獲取出來 (暫不考慮!important) 。
2. 外聯(lián)的層疊樣式
DOM2樣式規(guī)范在document.defaultView中包含了一個(gè)getComputedStyle()方法。該方法返回一個(gè)只讀的CSSStyleDeclaration對(duì)象,其中包含特定元素的所有計(jì)算樣式。
四、解題
4.1 將所有工具方法封裝在WDS(wall dom script)命名空間中
(function(WDS, undefined){ // 封裝代碼... })(window.WDS || (window.WDS = {}));
代碼封裝在命名空間里,不會(huì)造成無意間的代碼污染。
4.2 工具方法camelize
// 字符串轉(zhuǎn)換為駝峰寫法 function camelize(str) { return str.replace(/-(\w)/g, function (strMatch, p1){ return p1.toUpperCase(); }); }
該方法是為了方便后續(xù)getStyle()方法的編寫,而獨(dú)立出來的。
作用是將連字符類的css屬性值,轉(zhuǎn)換成駝峰寫法。
例如:將background-color轉(zhuǎn)換為backgroundColor
4.3 獲取特定元素的計(jì)算樣式
// 獲取元素計(jì)算后的樣式 function getStyle(elem, property){ if(!elem || !property){ return false; } var value = elem.style[camelize(property)], // 先獲取是否有內(nèi)聯(lián)樣式 css; // 獲取的所有計(jì)算樣式 // 無內(nèi)聯(lián)樣式,則獲取層疊樣式表計(jì)算后的樣式 if(!value){ if(document.defaultView && document.defaultView.getComputedStyle){ css = document.defaultView.getComputedStyle(elem, null); value = css ? css.getPropertyValue(property) : null; } } return value; }
做到這一步,第一個(gè)考察點(diǎn)基本就滿足了。也能獲知面試者是否具備足夠扎實(shí)的js基礎(chǔ)。
另外,像安全保護(hù)性的判斷if(!elem || !property)和功能嗅探if(document.defaultView && document.defaultView.getComputedStyle),都能很好地體現(xiàn)開發(fā)者的代碼邏輯和開發(fā)經(jīng)驗(yàn)。
4.4 排除特殊情況
// 檢測(cè)獲取的背景色是否有效 function checkBgValue(elem){ var value = getStyle(elem, 'background-color'), hasColor = value ? true : false; // 是否有顏色 // 排除特殊情況 if(value == "transparent" || value == "rgba(0, 0, 0, 0)"){ // 未設(shè)置background-color,或者設(shè)置為跟隨父節(jié)點(diǎn) hasColor = false; }else if(getStyle(elem, 'opacity') == "0"){ // dom節(jié)點(diǎn)透明度為全透明 hasColor = false; }else if(getStyle(elem, 'visibility') == "hidden"){ // dom節(jié)點(diǎn)不可見 hasColor = false; }else if(getStyle(elem, 'display') == "none"){ // dom節(jié)點(diǎn)不可見 hasColor = false; } return hasColor; }
4.5 獲取div在頁面最終顯示的顏色
// 獲取div最終顯示的顏色 function getRealBg(elem){ if(checkBgValue(elem)){ return getStyle(elem, 'background-color'); }else if(elem != document.documentElement){ return getRealBg(elem.parentNode); } return ''; }
獲取樣式值采用遞歸方式處理。
如果能順利獲取到元素樣式,且不觸發(fā)4.4 排除特殊情況中的一種,則直接返回結(jié)果。
觸發(fā)了特殊情況,則需要查找父節(jié)點(diǎn)以及更上層的節(jié)點(diǎn)的樣式,來獲取肉眼能看到,顯示在頁面上的background-color值。
在向上回溯的過程中,如果已經(jīng)回溯到html根節(jié)點(diǎn),則可以停止回溯。所以加了判斷else if(elem != document.documentElement)
五、遺漏的大boss
5.1 大boss !important
如果亂用 !important,對(duì)大型項(xiàng)目的維護(hù)和開發(fā),絕對(duì)是一場(chǎng)噩夢(mèng)。因?yàn)閮?yōu)先級(jí)規(guī)則的計(jì)算,!important永遠(yuǎn)處在食物鏈的最頂層。
當(dāng)前題目不考慮這種情況,也是我的偷懶??。確實(shí)很棘手,就不寫這個(gè)邏輯分支的代碼了。這里提醒一下~
5.2 大boss 父節(jié)點(diǎn)及根節(jié)點(diǎn)設(shè)置了不可見css屬性
只要設(shè)置該css語句:html {display:none;},頁面所有元素立刻消失不見。而任意特定元素的上級(jí)節(jié)點(diǎn),只要設(shè)置了 opacity,display,visibility,判斷邏輯瞬間變得復(fù)雜起來。所以,這個(gè)渾水我也不趟 O(∩_∩)O哈哈~
六、改進(jìn)的點(diǎn)
其實(shí)特殊情況排除的判斷,我偷懶沒做到最好——rgb顏色值和特定顏色值(比如red)沒有進(jìn)行統(tǒng)一的轉(zhuǎn)換,只是加了生硬的判斷if(value == "transparent" || value == "rgba(0, 0, 0, 0)")。
有興趣的可以搜索下顏色值轉(zhuǎn)換的js方法,這里我就不寫了。
七、源碼和demo
源碼地址:https://github.com/wall-wxk/blogDemo/blob/master/2017/02/05/getStyle.html
demo:https://wall-wxk.github.io/blogDemo/2017/02/05/getStyle.html
以上就是本文的全部?jī)?nèi)容,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來一定的幫助,同時(shí)也希望多多支持腳本之家!
- BootStrap Table 獲取同行不同列元素的方法
- jQuery獲取this當(dāng)前對(duì)象子元素對(duì)象的方法
- js通過classname來獲取元素的方法
- javascript中獲取元素標(biāo)簽中間的內(nèi)容的實(shí)現(xiàn)方法
- JS獲取html元素的標(biāo)記名實(shí)現(xiàn)方法
- js獲取元素的標(biāo)簽名實(shí)現(xiàn)方法
- jQuery實(shí)現(xiàn)獲取元素索引值index的方法
- jQuery元素屬性操作實(shí)例(設(shè)置、獲取及刪除元素屬性)
- js 獲取元素所有兄弟節(jié)點(diǎn)的實(shí)現(xiàn)方法
- 原生js獲取元素樣式的簡(jiǎn)單方法
- JQuery獲取樣式中的background-color顏色值的問題
相關(guān)文章
關(guān)于JavaScript回調(diào)函數(shù)的深入理解
由于函數(shù)是一等對(duì)象,我們可以把一個(gè)函數(shù)作為參數(shù)傳遞給另一個(gè)函數(shù),然后在那個(gè)函數(shù)內(nèi)執(zhí)行,至也可以被那個(gè)函數(shù)返回,然后再執(zhí)行,這篇文章主要給大家介紹了關(guān)于JavaScript回調(diào)函數(shù)的深入理解,需要的朋友可以參考下2021-06-06JavaScript實(shí)現(xiàn)算術(shù)平方根算法-代碼超簡(jiǎn)單
實(shí)現(xiàn)算術(shù)平方根的方法有很多種,本文是通過JavaScript實(shí)現(xiàn)的算術(shù)平方根算法,代碼超簡(jiǎn)單,超管用,感興趣的朋友跟著腳本之家的小編一起學(xué)習(xí)吧2015-09-09用javascript模仿ie的自動(dòng)完成類似自動(dòng)完成功的表單
最近在寫一個(gè)javascript框架,看見網(wǎng)上有不少自動(dòng)完成功能的表單,于是用javascript寫了一個(gè),需要的朋友可以參考下2012-12-12用javascript實(shí)現(xiàn)的仿Flash廣告圖片輪換效果
用javascript實(shí)現(xiàn)的仿Flash廣告圖片輪換效果...2007-04-04ES6 Symbol在對(duì)象中的作用實(shí)例分析
這篇文章主要介紹了ES6 Symbol在對(duì)象中的作用,結(jié)合實(shí)例形式分析了ES6 Symbol在對(duì)象中聲明、使用方法與相關(guān)注意事項(xiàng),需要的朋友可以參考下2020-06-06JavaScript限定復(fù)選框的選擇個(gè)數(shù)示例代碼
有10個(gè)復(fù)選框,用戶最多只能勾選3個(gè),否則就灰掉所有復(fù)選框,具體實(shí)現(xiàn)思路及代碼如下,感興趣的朋友可以參考下,希望對(duì)大家有所幫助2013-08-08純css+js寫的一個(gè)簡(jiǎn)單的tab標(biāo)簽頁帶樣式
最近經(jīng)常要用tab標(biāo)簽頁,于是就寫了一個(gè)簡(jiǎn)單的tab標(biāo)簽頁,純css+js寫的,帶樣式。大家可以參考下2014-01-01Apply an AutoFormat to an Excel Spreadsheet
Apply an AutoFormat to an Excel Spreadsheet...2007-06-06javascript實(shí)現(xiàn)右側(cè)彈出“分享到”窗口效果
這篇文章主要為大家介紹了javascript實(shí)現(xiàn)右側(cè)彈出“分享到”窗口效果,以一個(gè)完整的js右側(cè)彈出“分享到”窗口的實(shí)例代碼進(jìn)行分析,感興趣的小伙伴們可以參考一下2016-02-02javascript中節(jié)點(diǎn)的最近的相關(guān)節(jié)點(diǎn)訪問方法
parentNode——父節(jié)點(diǎn);firstChild——第一個(gè)子節(jié)點(diǎn);lastChild——最后一個(gè)子節(jié)點(diǎn);previousSibling——緊挨著的前面的兄弟節(jié)點(diǎn);這樣就可以作短途旅行,訪問當(dāng)前節(jié)點(diǎn)的某些相關(guān)節(jié)點(diǎn),感興趣的你可以參考下哈2013-03-03