摘要:而且它還是只讀的屬性,所以通過(guò)來(lái)改變樣式,如果不能修改文件的情況下,只能采用內(nèi)聯(lián)。一般的思路就是,先看看有沒(méi)有內(nèi)聯(lián),如果沒(méi)有內(nèi)聯(lián),就走一般流程。
歡迎來(lái)我的專欄查看系列文章。
樣式操作也是 jQuery 比較常用的一個(gè)操作,就我本人而言,這個(gè) css 函數(shù)用多了,感覺(jué)自己有點(diǎn)傻乎乎的,主要還是自己不了解 js 中 css 的真正含義。
不過(guò)現(xiàn)在不怕了。
開(kāi)始之前,先拋開(kāi) jQuery,我們來(lái)看看一個(gè)有趣的面試題(據(jù)說(shuō)是一道微信面試題)。
一道很有深度的面試題用原生的 js 獲得一個(gè) HTML 元素的 background-color,當(dāng)然,這只是一個(gè)引入,為什么不是 color,為什么不是 font-size?
css 渲染的優(yōu)先級(jí)寫(xiě)過(guò) css 樣式的同學(xué)都知道,css 是有優(yōu)先級(jí)區(qū)分的,!important優(yōu)先級(jí)最高,內(nèi)聯(lián)優(yōu)先級(jí)其次,id,類和偽類,元素和偽元素。優(yōu)先級(jí)會(huì)按照順序依次比較,同一級(jí)別相同則看下一級(jí)別,優(yōu)先級(jí)相同,后面會(huì)覆蓋前面。
比如,就像理科生排成績(jī),規(guī)定 總分 > 數(shù)學(xué) > 語(yǔ)文 > 英語(yǔ),如果 A,B 兩人總分一樣,就看數(shù)學(xué)成績(jī)誰(shuí)高,數(shù)學(xué)成績(jī)一樣,就看語(yǔ)文成績(jī)誰(shuí)高,以此類推。
記得在一家公司實(shí)習(xí)的時(shí)候(初學(xué)者),那個(gè)時(shí)候修改網(wǎng)站的主頁(yè)樣式,由于找不到樣式對(duì)應(yīng),就大量使用 !important,并把所有樣式都寫(xiě)在樣式標(biāo)的最后,估計(jì),后面接手的人要?dú)庹ò伞?/p>
問(wèn)題來(lái)了,對(duì)于任意的一個(gè) elem,DIV 也好,P 也好,都只會(huì)保留一個(gè) style 樣式表,一般可以通過(guò) getComputedStyle 函數(shù)或 IE 的 currentStyle 參數(shù)活動(dòng)(萬(wàn)惡的 IE,現(xiàn)在 jQuery 已經(jīng)不支持低版本 IE,連淘寶都不支持 IE8 了)。無(wú)論這個(gè)樣式表是通過(guò)前面哪個(gè)優(yōu)先級(jí)獲得的,但它一定是唯一且只有一個(gè)。而且它還是只讀的屬性,所以通過(guò) JS 來(lái)改變樣式,如果不能修改 css 文件的情況下,只能采用內(nèi)聯(lián)。
內(nèi)聯(lián)有兩種,一種是在 elem 上添加一個(gè) style 屬性,還有一種是在 HTMl 新建一個(gè) 標(biāo)簽,很顯然,第一種貌似更符合 js 的特性,因?yàn)檎业侥莻€(gè) elem 并不困難,而且還有一個(gè) elem.style 可以使用。
js 獲取元素樣式elem.style 并不是萬(wàn)能的,也有很大的局限性。一般的思路就是,先看看有沒(méi)有內(nèi)聯(lián),如果沒(méi)有內(nèi)聯(lián),就走一般流程。
內(nèi)聯(lián)值和 getComputedStyle 的值會(huì)不一樣嗎,我自己做過(guò)測(cè)試,在 chrome 下面,內(nèi)聯(lián)值和樣式表 getComputedStyle 的值是一樣的,而且,當(dāng)內(nèi)聯(lián)值改變,樣式表也會(huì)跟著改變,除非在 css 文件中有比內(nèi)聯(lián)優(yōu)先級(jí)還高的 important,這個(gè)時(shí)候內(nèi)聯(lián)是不起作用的,只能通過(guò)樣式表來(lái)獲取。
var dom = document.getElementById("test"); var styleList = getComputedStyle(dom); styleList.color; // "black" dom.style.color = "red"; // 會(huì)自動(dòng)刷新的 styleList.color; // "red"
當(dāng) styleList.color 不變的時(shí)候,就知道可能有 important 樣式的存在,也可以作為判斷 important 的一個(gè)標(biāo)準(zhǔn)。
樣式表有 font-size,有人寫(xiě)成駝峰 fontSize,這可以理解,統(tǒng)一一下就好啦。由于 elem.style 和 getComputedStyle 使用的是駝峰寫(xiě)法(實(shí)際上即使用破折法去獲取也是可以得到的)要借助下面這兩個(gè)函數(shù)來(lái):
// 變成駝峰 function camel(str){ return str.replace(/-(w)/g, function(m0, m1){ return m1.toUpperCase(); }) } // 變成破折 function dashes(str){ return str.replace(/[A-Z]/g, function(m0){ return "-" + m0.toLowerCase(); }) }
因此:
function getStyle(elem, name){ var value, styles, sty; if(!name){ // 只有一個(gè)參數(shù),直接返回吧 return false; } if(elem.nodeType !==1 && elem.nodeType !== 9 && elem.nodeType !== 11){ // 肯定不是 HTMLElement return false; } name = camel(name); //將 name 轉(zhuǎn)變成駝峰 value = elem.style[name]; if(value){ return value; } styles = (sty = elem.currentStyle) ? sty : (sty = document.defaultView.getComputedStyle) ? sty(elem) : {}; return (sty = styles[name]) ? sty : false; } // 測(cè)試,無(wú)視駝峰和破折 getStyle(dom, "font-size"); // "16px" getStyle(dom, "fontSize"); // "16px"
這道題目還是很有意思的,當(dāng)然,答案還不止,還可以繼續(xù)優(yōu)化,這樣可以給面試官好感,鏈接。
因?yàn)槲覀儨y(cè)的是 background-color,這個(gè)屬性很特別,當(dāng)它是 inherit表示繼承父類,transparent 表示透明,也該為 flase,看:
function fixColor(elem){ var color = getStyle(elem, "background-color"); if(color){ if(color == "transparent" || color == "rgba(0, 0, 0, 0)") return false; else if(getStyle(elem, "opacity") == "0"){ return false; // 透明 } else if(getStyle(elem, "display") == "none"){ return false; // none } else if(getStyle(elem, "visibility") == "hidden"){ return false; // 隱藏 } } if(color == "inherit"){ // 繼承父 return elem.parentNode ? fixColor(elem.parentNode) : false; } return color; }
越來(lái)越有意思了。如果是 html5 中的 canvas,貌似又要去找。
fn.css() 源碼好吧,步入正題了。我想,如果仔細(xì)看了前面面試題的同學(xué),也該對(duì)原生 js 操作 css 做法完全懂了,jQuery 的思路也完全是如此,只是多了更多的兼容考慮:
jQuery.fn.extend( { css: function( name, value ) { return access( this, function( elem, name, value ) { var styles, len, map = {}, i = 0; if ( jQuery.isArray( name ) ) { styles = getStyles( elem ); len = name.length; for ( ; i < len; i++ ) { map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); } return map; } return value !== undefined ? jQuery.style( elem, name, value ) : jQuery.css( elem, name ); }, name, value, arguments.length > 1 ); } } );
css 也是有 set 和 get 的,但是它們并不在 fn.css 函數(shù)里處理,set 對(duì)應(yīng) jQuery.style,get 對(duì)應(yīng) jQuery.css。
在此之前,先來(lái)看一個(gè)很熟悉的函數(shù):
var getStyles = function( elem ) { // Support: IE <=11 only, Firefox <=30 (#15098, #14150) // IE throws on elements created in popups // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" var view = elem.ownerDocument.defaultView; if ( !view || !view.opener ) { view = window; } return view.getComputedStyle( elem ); };
jQuery 已經(jīng)不支持 currentStyle,也就是拋棄了低版本 IE 瀏覽器。
jQuery.extend( { camelCase: function( string ) { return string.replace( /^-ms-/, "ms-" ).replace( /-([a-z])/g, function( all, letter ) { return letter.toUpperCase(); } ); } } );
camelCase 也是一個(gè)很熟悉的函數(shù)(ms 是有其他用途的)。
jQuery.extend( { style: function( elem, name, value, extra ) { // 處理特殊情況 !elem.style 可以借鑒 if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { return; } // Make sure that we"re working with the right name var ret, type, hooks, origName = jQuery.camelCase( name ), style = elem.style; name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( origName ) || origName ); // hooks hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; // Check if we"re setting a value if ( value !== undefined ) { type = typeof value; // Convert "+=" or "-=" to relative numbers (#7345) if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { value = adjustCSS( elem, name, ret ); // Fixes bug #9237 type = "number"; } // Make sure that null and NaN values aren"t set (#7116) if ( value == null || value !== value ) { return; } // If a number was passed in, add the unit (except for certain CSS properties) if ( type === "number" ) { value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); } // background-* props affect original clone"s values if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { style[ name ] = "inherit"; } // If a hook was provided, use that value, otherwise just set the specified value if ( !hooks || !( "set" in hooks ) || ( value = hooks.set( elem, value, extra ) ) !== undefined ) { style[ name ] = value; } } else { // If a hook was provided get the non-computed value from there if ( hooks && "get" in hooks && ( ret = hooks.get( elem, false, extra ) ) !== undefined ) { return ret; } // 千辛萬(wàn)苦,終于等到你 return style[ name ]; } } } );
jQuery.extend( { css: function( elem, name, extra, styles ) { var val, num, hooks, origName = jQuery.camelCase( name ); // Make sure that we"re working with the right name name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( origName ) || origName ); // Try prefixed name followed by the unprefixed name hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; // If a hook was provided get the computed value from there if ( hooks && "get" in hooks ) { val = hooks.get( elem, true, extra ); } // Otherwise, if a way to get the computed value exists, use that if ( val === undefined ) { val = curCSS( elem, name, styles ); } // Convert "normal" to computed value if ( val === "normal" && name in cssNormalTransform ) { val = cssNormalTransform[ name ]; } // Make numeric if forced or a qualifier was provided and val looks numeric if ( extra === "" || extra ) { num = parseFloat( val ); return extra === true || isFinite( num ) ? num || 0 : val; } return val; } } );總結(jié)
如果你對(duì) css 看起來(lái)很吃力,請(qǐng)把那個(gè)微信面試題再仔細(xì)閱讀一下吧。
參考解密jQuery內(nèi)核 樣式操作
CSS并不簡(jiǎn)單--一道微信面試題的實(shí)踐
微信面試題-獲取元素的最終background-color
本文在 github 上的源碼地址,歡迎來(lái) star。
歡迎來(lái)我的博客交流。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/86828.html
摘要:需要把的元信息從中解析出來(lái),做一些檢查,然后把的元信息持久化保存到中。主要做件事修改的元信息,把加入到的元信息中去。從隊(duì)列中取出,根據(jù)的類型調(diào)用函數(shù)。的狀態(tài)變?yōu)橹螅瑫?huì)調(diào)用將的元信息從上刪除。 DDL 是數(shù)據(jù)庫(kù)非常核心的組件,其正確性和穩(wěn)定性是整個(gè) SQL 引擎的基石,在分布式數(shù)據(jù)庫(kù)中,如何在保證數(shù)據(jù)一致性的前提下實(shí)現(xiàn)無(wú)鎖的 DDL 操作是一件有挑戰(zhàn)的事情。本文首先會(huì)介紹 TiDB D...
摘要:一團(tuán)隊(duì)組織網(wǎng)站說(shuō)明騰訊團(tuán)隊(duì)騰訊前端團(tuán)隊(duì),代表作品,致力于前端技術(shù)的研究騰訊社交用戶體驗(yàn)設(shè)計(jì),簡(jiǎn)稱,騰訊設(shè)計(jì)團(tuán)隊(duì)網(wǎng)站騰訊用戶研究與體驗(yàn)設(shè)計(jì)部百度前端研發(fā)部出品淘寶前端團(tuán)隊(duì)用技術(shù)為體驗(yàn)提供無(wú)限可能凹凸實(shí)驗(yàn)室京東用戶體驗(yàn)設(shè)計(jì)部出品奇舞團(tuán)奇虎旗下前 一、團(tuán)隊(duì)組織 網(wǎng)站 說(shuō)明 騰訊 AlloyTeam 團(tuán)隊(duì) 騰訊Web前端團(tuán)隊(duì),代表作品WebQQ,致力于前端技術(shù)的研究 ISUX 騰...
摘要:一團(tuán)隊(duì)組織網(wǎng)站說(shuō)明騰訊團(tuán)隊(duì)騰訊前端團(tuán)隊(duì),代表作品,致力于前端技術(shù)的研究騰訊社交用戶體驗(yàn)設(shè)計(jì),簡(jiǎn)稱,騰訊設(shè)計(jì)團(tuán)隊(duì)網(wǎng)站騰訊用戶研究與體驗(yàn)設(shè)計(jì)部百度前端研發(fā)部出品淘寶前端團(tuán)隊(duì)用技術(shù)為體驗(yàn)提供無(wú)限可能凹凸實(shí)驗(yàn)室京東用戶體驗(yàn)設(shè)計(jì)部出品奇舞團(tuán)奇虎旗下前 一、團(tuán)隊(duì)組織 網(wǎng)站 說(shuō)明 騰訊 AlloyTeam 團(tuán)隊(duì) 騰訊Web前端團(tuán)隊(duì),代表作品WebQQ,致力于前端技術(shù)的研究 ISUX 騰...
閱讀 1199·2021-10-11 10:59
閱讀 1979·2021-09-29 09:44
閱讀 866·2021-09-01 10:32
閱讀 1441·2019-08-30 14:21
閱讀 1883·2019-08-29 15:39
閱讀 2990·2019-08-29 13:45
閱讀 3546·2019-08-29 13:27
閱讀 2017·2019-08-29 12:27