css類選擇器或邏輯,深入理解CSS中選擇器的邏輯處理

在過去的很長一段時間中,我們都說 CSS 是不帶有任何邏輯的,意思是在 CSS 中沒有控制流,也沒有某種類似于其他編程語言的方式來組織 CSS。CSS 天生缺乏邏輯性的問題導致了預處理器的出現。然而業界卻對 CSS 預處理器褒貶不一,支持預處理器的人認為這彌補了 CSS 缺失的特性;而反對預處理器的人則認為 CSS 的設計初衷就不應該帶有邏輯性,他們認為根本不應該引入預處理器這個概念。

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

我發現我們可以將復合選擇器理解為:主體部分 + 條件部分。首先來看一個例子:

CSS Code復制內容到剪貼板

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

/*...*/

}

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

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

CSS Code復制內容到剪貼板

@if?exists(span)?{

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

@if?is-on(a)?{

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

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

@if?is-on(div)?{

#?Do?this.

}

}

}

}

}

}

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

CSS Code復制內容到剪貼板

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

#?Do?this.

}

每當為選擇器添加一層限制,其實我們也就是添加了額外的一個 if 語句。這會導致圈復雜度問題(Cyclomatic Complexity)。

圈復雜度

在軟件工程中,圈復雜度是一種程序復雜性的一種度量標準,它一般計算程序中的控制流的數量(如 if, else, while 等)。程序中存在越多的控制流,則圈復雜度就越高。我們自然想要保證圈復雜度能夠盡量地低,因為圈復雜度越高:

代碼就越難推導

更多潛藏著的、可能會導致失敗的問題

代碼更難以修改、維護以及復用

你需要考慮更多代碼執行的結果與其副作用

編寫測試代碼的難度也會更高

從圈復雜度的角度來思考 CSS 的解析過程,我們可以看到瀏覽器在渲染樣式之前需要做許多的決定。我們寫的選擇器中的 if 語句越多,這個選擇器的圈復雜度就越高,這也意味著我們寫的選擇器越糟糕,為了使得這一條選擇器規則滿足,就有需要匹配更多的條件。同時,我們寫的選擇器也會缺乏清晰度和復用性,因為引入了過多不必要的 if 語句會導致不準確的匹配(false positive)。

相比于將 span 嵌套于 .btn 內部并寫一大堆限制條件,更好地做法應該是創建一個新的類 .btn-text 來描述這個 span。這樣做更加直截了當,同時也更為簡潔和健壯(越多的 @if 語句導致選擇器規則越不容易被滿足)。

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

請不要寫過于寬泛的規則,導致你寫的選擇器在匹配開始時就選中大量的 DOM 元素——然后不得不逐步通過更多的條件語句來刪減匹配的對象。從選擇器的規則解析的一開始就匹配盡量少的元素才是一種更棒的方法。

圈復雜度對于 CSS 來說可能是一種比較高階的原則,但如果我們通過它來考量那些蘊含在我們寫的選擇器中的邏輯性,那我們也許就能寫出更加優秀的代碼。

一些易于遵守的小規則,

讓你的選擇器最簡化:每一次你想要為選擇器添加規則時,你都在添加額外的 if 語句。將這些 if 語句大聲地讀出來,仔細考慮它們是否有添加的必要。你需要時刻保持你寫的選擇器足夠合理與簡潔。

保證圈復雜度最小化: 使用像 Parker 這樣的工具來測試你寫的選擇器的圈復雜度(參考文檔:Identifiers Per Selector)

如果你不需要這個檢驗條件,那就不要把它放進選擇器: 有時在 CSS 中使用嵌套結構是有必要的,可在大多數時候并不是,你甚至不能完全相信Inception Rule。

從右邊考慮選擇器如何編寫: 從需要匹配的那類元素開始,寫盡量少的額外的 CSS 代碼來完成一次正確的匹配。

寫選擇器時擁有明確的目的性: 確保你寫的選擇器確實是你想要的,而不是那些碰巧能使得頁面正常顯示的代碼。

你的選擇器是你的 CSS 結構最基本的組成部分,一定要確保你寫的代碼足夠合理而簡練。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/371888.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/371888.shtml
英文地址,請注明出處:http://en.pswp.cn/news/371888.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

JSF基于事件的交流:新派方法

在上一篇文章中 ,我們學習了基于Observer / Event Listener和Mediator模式的基于事件的通信。 由于它們的缺點,我想展示基于事件的通信的更有效方法。 我們將從Google Guava EventBus開始,以CDI (Java EE平臺的上下文和依賴注入&a…

菜鳥之路-淺談設計模式之單例設計模式

單例設計模式 定義:確保一個類僅僅有一個實例,并且自行實例化并向整個系統提供這個實例。單例模式是一種經常使用的軟件設計模式。在它的核心結構中僅僅包括一個被稱為單例的特殊類。通過單例模式能夠保證系統中一個類僅僅有一個實例并且該實例易于外界訪…

python 32bit數據結構_python實現bitmap數據結構詳解

bitmap是很常見的算法設計,例如用以Bloom Filter中;用以無反復整數金額的排列這些。bitmap一般根據數組來完成,數組中每一個原素能夠當做是一系列二進制數,全部元素組成更高的二進制結合。針對Python而言,整數金額種類…

MVC如何使用開源分頁插件shenniu.pager.js

最近比較忙,前期忙公司手機端接口項目,各種開發調試發布現在幾乎上線無問題了;雖然公司項目忙不過在期間抽空做了兩件個人覺得有意義的事情,一者使用aspnetcore開發了個人線上項目(要說線上其實只能ip訪問,…

四. 基于環視Camera的BEV感知算法-PETR

目錄 前言0. 簡述1. 算法動機&開創性思路2. 主體結構3. 損失函數4. 性能對比5. PETRv2總結下載鏈接參考 前言 自動駕駛之心推出的《國內首個BVE感知全棧系列學習教程》,鏈接。記錄下個人學習筆記,僅供自己參考 本次課程我們來學習下課程第四章——基…

Java EE 6 VS Spring 3:Java EE已經殺死了Spring? 沒門!

介紹 幾天前,我在聽Java Spotlight Podcast的插曲85 。 在這次演講中, Bert Ertman和Paul Bakker討論了從Spring遷移到Java EE。 基本上,在他們的介紹中,他們說,如今,選擇Spring而不是Java EE是沒有意義的。…

usb檢測串口是哪個角_怎樣測試串口和串口線是否正常

一步:把串口線或者USB轉串口線插到計算機上。二步:打開串口調試助手接著選擇串口,串口線和 USB 轉串口的端口號查看路徑:電腦上--右鍵--屬性--硬件--設備管理器-端口(COM 和LPT),點開端口前面的號查看即可。注釋:1、US…

NodeJS常用模塊介紹

收集了NodeJS開發中常用的一些模塊。MVC框架 - Express Express 是輕量靈活的Nodejs Web應用框架,它可以快速地搭建網站。Express框架建立在Nodejs內置的Http模塊上,并對Http模塊再包裝,從而實際Web請求處理的 功能。它支持多種前端模板&…

Java泛型面試問題

Java面試中的通用面試問題在相當長的時間內在Java 5周圍越來越普遍,許多應用程序都轉移到Java 5上,并且幾乎所有新的Java開發都發生在Tiger(Java 5的代號)上。 泛型和Java 5功能(例如Enum)的重要性&#xf…

隱層元素閃一下_太陽一直依靠什么元素在燃燒,地球上的重元素又是怎么來的?...

本文基于回答網友一個這樣的問題:太陽目前氫核聚變是氦碳氧穩定燃燒地球上的鐵鎳重元素哪里來的?可以說,這是一個毫無邏輯亂七八糟的問題,但既然邀請回答,就從中挑出幾個稍顯合理的問題說明一下。太陽核心每時每刻都在…

基于Token的WEB后臺認證機制

基于Token的WEB后臺認證機制 幾種常用的認證機制 HTTP Basic Auth HTTP Basic Auth簡單點說明就是每次請求API時都提供用戶的username和password,簡言之,Basic Auth是配合RESTful API 使用的最簡單的認證方式,只需提供用戶名密碼即可&#xf…

JSF基于事件的溝通:過時的方法

用JSF編寫的Web應用程序由相互交互的bean組成。 在開發Web應用程序時,bean之間的通信是主要的設計模式之一。 有時,一個bean需要向其他bean發送事件,以通知它們某些更改或其他任何更改。 我們通常可以將托管bean或Spring bean注入另一個bean的…

mysql調優 基礎

MySQL調優可以從幾個方面來做:1. 架構層:做從庫,實現讀寫分離;2.系統層次:增加內存;給磁盤做raid0或者raid5以增加磁盤的讀寫速度;可以重新掛載磁盤,并加上noatime參數,這…

saltstack

第一:安裝前準備: 聲明我用的是ubuntu 16.04的系統 1.修改主機名,并保證兩臺機器可以互相ping同主機名 ip1 master_hostname ip2 slave_hostname 第二:安裝 服務器安裝 yum install salt-master -y客戶端安裝 yum install salt…

ios 百度地圖指定區域_獲取百度地圖可視區域范圍的數據

有個業務場景,需要根據獲取到的地圖區域顯示,根據相應的經緯度反查 左側區域的會議室。思路:1.得到百度地圖可視區域--可視區域的中心點2.可視區域的四個角的其中兩個(東北角西南角)http://lbsyun.baidu.com/cms/jsapi/reference/jsapi_refer…

使用WS-Trust / STS采樣器擴展JMeter

JMeter沒有對WS-Security或WS-Trust的任何內置支持,這使我為JMeter開發了此STS Sampler –可以在負載測試STS時使任何人的生活變得更好。 首先,您需要擁有Apache JMeter發行版。 我正在使用v2.7。 然后,您可以從此處下載sts.sampler.zip –解…

分享一個使用閉包對一個對象繼承方式

function Person(name,age){this.name name;this.age age; }//定義一個new函數 繼承了對Person的繼承 function New(obj){return function(){var o {"__proto__":obj.proto};obj.apply(o,arguments);}return obj; }var n new New(Person)("對象繼承了person…

vue怎么改logo_vue全家桶項目構建教程

前言vue是現階段很流行的前端框架,很多人通過vue官方文檔的學習,對vue的使用都有了一定的了解,但再在項目工程化處理的時候,卻發現不知道改怎么更好的管理自己的項目,如何去引入一些框架以及vue全家桶其他框架的使用&a…

EclipseLink MOXy作為JAXB提供者

EclipseLink MOXy是JAXB提供程序,并且是內置在JDK中的默認JAXB提供程序的引人注目的替代品。 首先是一個簡單的測試,將Java對象編組為XML: 這是模型: XmlRootElement(nameMemberDetailsRequest, namespacehttp://bk.org/members…

monkeyrunner多點觸摸

思路是:在屏幕上某個位置按著不放:device.touch(x,y,md.DOWN) 然后再做一個滑動的操作:device.drap((x1,y1),(x2,y2),0.2,10) 然后再松開按鍵:device.touch(x,y,md.UP) #codeing:utf-8 from com.android.monkeyrunner import Monk…