溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

如何理解CSS中選擇器的邏輯處理

發(fā)布時(shí)間:2021-09-17 17:44:05 來(lái)源:億速云 閱讀:133 作者:柒染 欄目:web開(kāi)發(fā)

這篇文章給大家介紹如何理解CSS中選擇器的邏輯處理,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對(duì)大家能有所幫助。

在過(guò)去的很長(zhǎng)一段時(shí)間中,我們都說(shuō) CSS 是不帶有任何邏輯的,意思是在 CSS 中沒(méi)有控制流,也沒(méi)有某種類(lèi)似于其他編程語(yǔ)言的方式來(lái)組織 CSS。CSS 天生缺乏邏輯性的問(wèn)題導(dǎo)致了預(yù)處理器的出現(xiàn)。然而業(yè)界卻對(duì) CSS 預(yù)處理器褒貶不一,支持預(yù)處理器的人認(rèn)為這彌補(bǔ)了 CSS 缺失的特性;而反對(duì)預(yù)處理器的人則認(rèn)為 CSS 的設(shè)計(jì)初衷就不應(yīng)該帶有邏輯性,他們認(rèn)為根本不應(yīng)該引入預(yù)處理器這個(gè)概念。

然而,一種獨(dú)特的思考方法最近突然蹦入了我的腦袋。它讓我感到 CSS 確實(shí)擁有邏輯性!很少有人真正那么想過(guò),這大概也是我們一直認(rèn)為 CSS 的邏輯性匱乏的最大原因吧。

我發(fā)現(xiàn)我們可以將復(fù)合選擇器理解為:主體部分 + 條件部分。首先來(lái)看一個(gè)例子:

CSS 

  1. div.sidebar .login-box a.btn span {   

  2.     /*...*/  

  3. }  

在這個(gè)復(fù)合選擇器由主體部分是 span,而條件部分是 IF (inside .btn) AND IF (on a) AND IF (inside .login-box) AND IF (inside .sidebar) AND IF (on div)。

也就是說(shuō),一個(gè)選擇器的每一部分都是一個(gè) if 語(yǔ)句,需要在解析選擇器時(shí)被滿(mǎn)足(或者不滿(mǎn)足)。有了這種微妙的而又全新的認(rèn)識(shí),如今我們回頭再看看自己曾經(jīng)寫(xiě)出的 CSS 代碼,我們將會(huì)意識(shí)到選擇器寫(xiě)的好或者壞,會(huì)對(duì)效率產(chǎn)生直接的影響。我們真的會(huì)寫(xiě)出下面這段邏輯嗎?(偽代碼):

CSS

  1. @if exists(span) {   

  2.   @if is-inside(.btn) {   

  3.     @if is-on(a) {   

  4.       @if is-inside(.login-box) {   

  5.         @if is-inside(.sidebar) {   

  6.           @if is-on(div) {   

  7.             # Do this.   

  8.           }   

  9.         }   

  10.       }   

  11.     }   

  12.   }   

  13. }  

也許不會(huì)。這看上去太不直接,也太啰嗦了。我們也許只需要這么寫(xiě):

CSS 

  1. @if exists(.btn-text) {   

  2.   

  3.   # Do this.   

  4.   

  5. }  

每當(dāng)為選擇器添加一層限制,其實(shí)我們也就是添加了額外的一個(gè) if 語(yǔ)句。這會(huì)導(dǎo)致圈復(fù)雜度問(wèn)題(Cyclomatic Complexity)。
圈復(fù)雜度

在軟件工程中,圈復(fù)雜度是一種程序復(fù)雜性的一種度量標(biāo)準(zhǔn),它一般計(jì)算程序中的控制流的數(shù)量(如 if, else, while 等)。程序中存在越多的控制流,則圈復(fù)雜度就越高。我們自然想要保證圈復(fù)雜度能夠盡量地低,因?yàn)槿?fù)雜度越高:

    代碼就越難推導(dǎo)
    更多潛藏著的、可能會(huì)導(dǎo)致失敗的問(wèn)題
    代碼更難以修改、維護(hù)以及復(fù)用
    你需要考慮更多代碼執(zhí)行的結(jié)果與其副作用
    編寫(xiě)測(cè)試代碼的難度也會(huì)更高

從圈復(fù)雜度的角度來(lái)思考 CSS 的解析過(guò)程,我們可以看到瀏覽器在渲染樣式之前需要做許多的決定。我們寫(xiě)的選擇器中的 if 語(yǔ)句越多,這個(gè)選擇器的圈復(fù)雜度就越高,這也意味著我們寫(xiě)的選擇器越糟糕,為了使得這一條選擇器規(guī)則滿(mǎn)足,就有需要匹配更多的條件。同時(shí),我們寫(xiě)的選擇器也會(huì)缺乏清晰度和復(fù)用性,因?yàn)橐肓诉^(guò)多不必要的 if 語(yǔ)句會(huì)導(dǎo)致不準(zhǔn)確的匹配(false positive)。

相比于將 span 嵌套于 .btn 內(nèi)部并寫(xiě)一大堆限制條件,更好地做法應(yīng)該是創(chuàng)建一個(gè)新的類(lèi) .btn-text 來(lái)描述這個(gè) span。這樣做更加直截了當(dāng),同時(shí)也更為簡(jiǎn)潔和健壯(越多的 @if 語(yǔ)句導(dǎo)致選擇器規(guī)則越不容易被滿(mǎn)足)。

值得注意的是瀏覽器解析你寫(xiě)的選擇器的方式:從右向左。如果你在寫(xiě)你的選擇器時(shí),第一個(gè)想到的問(wèn)題是:“這是一個(gè) span 元素嗎?” 那你通常就會(huì)把選擇器寫(xiě)的過(guò)于冗繁。你應(yīng)該從另一個(gè)角度思考,寫(xiě)出清晰準(zhǔn)確的選擇器規(guī)則,徹底摒棄那些冗余的條件語(yǔ)句。

請(qǐng)不要寫(xiě)過(guò)于寬泛的規(guī)則,導(dǎo)致你寫(xiě)的選擇器在匹配開(kāi)始時(shí)就選中大量的 DOM 元素——然后不得不逐步通過(guò)更多的條件語(yǔ)句來(lái)刪減匹配的對(duì)象。從選擇器的規(guī)則解析的一開(kāi)始就匹配盡量少的元素才是一種更棒的方法。

圈復(fù)雜度對(duì)于 CSS 來(lái)說(shuō)可能是一種比較高階的原則,但如果我們通過(guò)它來(lái)考量那些蘊(yùn)含在我們寫(xiě)的選擇器中的邏輯性,那我們也許就能寫(xiě)出更加優(yōu)秀的代碼。

一些易于遵守的小規(guī)則,

    讓你的選擇器最簡(jiǎn)化:每一次你想要為選擇器添加規(guī)則時(shí),你都在添加額外的 if 語(yǔ)句。將這些 if 語(yǔ)句大聲地讀出來(lái),仔細(xì)考慮它們是否有添加的必要。你需要時(shí)刻保持你寫(xiě)的選擇器足夠合理與簡(jiǎn)潔。
    保證圈復(fù)雜度最小化: 使用像 Parker 這樣的工具來(lái)測(cè)試你寫(xiě)的選擇器的圈復(fù)雜度(參考文檔:Identifiers Per Selector)
    如果你不需要這個(gè)檢驗(yàn)條件,那就不要把它放進(jìn)選擇器: 有時(shí)在 CSS 中使用嵌套結(jié)構(gòu)是有必要的,可在大多數(shù)時(shí)候并不是,你甚至不能完全相信Inception Rule。
    從右邊考慮選擇器如何編寫(xiě): 從需要匹配的那類(lèi)元素開(kāi)始,寫(xiě)盡量少的額外的 CSS 代碼來(lái)完成一次正確的匹配。
    寫(xiě)選擇器時(shí)擁有明確的目的性: 確保你寫(xiě)的選擇器確實(shí)是你想要的,而不是那些碰巧能使得頁(yè)面正常顯示的代碼。

你的選擇器是你的 CSS 結(jié)構(gòu)最基本的組成部分,一定要確保你寫(xiě)的代碼足夠合理而簡(jiǎn)練。

關(guān)于如何理解CSS中選擇器的邏輯處理就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

css
AI