標籤:

為什麼 CSS :not 選擇器不支持複雜選擇?


實際上,最近的selector 4的草案是支持的。不僅是你給的例子(compound selector)支持,實際支持selector list(即所有選擇器)。

【以下是我的主觀看法,不保證準確,謹供參考。如需驗證,請自行查閱w3c mailing list記錄,或寫郵件諮詢spec的編輯,比如fantasai和Tab Atkins Jr.。】

過去(selector 3規範)確實僅支持單個simple selector。

我們需要理解,技術上可以做到不代表就應該直接上。

首先我們應該考慮需求,即實際的use cases。單個simple selector其實已經滿足了大量需求了。對於簡單的compound selector的需求,比如`a:not(.b.c)`,可以寫作`a:not(.b):not(.c), a.b:not(.c), a.c:not(.b)`。題主寫的`img:not(.abc[alt][href])`(這裡href估計是題主的筆誤,因為img上只有src屬性)也可以轉寫。當然,這比較麻煩,且如果多的話,很容易出現組合爆炸。不過當初連簡單的:not都沒有,人民群眾並不習慣逆向思維,更複雜的需求還沒有被發掘,也就是並沒有很多use cases。

其次,我們是希望新特性出來非常慢但是一步到位,還是先出一部分特性用起來呢?總的來說,後者更好。因為更快出可用的新特性,大家可以更快試驗,也就可以更快的給出反饋,廠商可以更快的發現和修復bug,標準工作組可以更快地確認真實的use cases,確認spec的設計是可行和合理的。此外,小步走可以在工程上控制複雜度,避免出現步子邁得太大扯到蛋。(比如CSS2就是一個反例。當初標準過於複雜,就不可能有足夠完善和完全的實現,各瀏覽器實現存在各種bug不說,更有許多是spec本身存在bug、未定義或含糊不清的地方。)當然,「小步走」的前提是你本身是有設計有規劃的。現在一些公司所謂的「小步走」實際是「快糙猛」,請大家注意甄別,千萬別混為一談。【PS. 「小步走」也絕不等於「摸著石頭過河」——所謂「摸石頭過河」是一種非常噁心的做法,因為其實質是忽悠大家連救生圈都不帶就下河,你若渡河成功算領導高瞻遠矚指揮有方,你若不幸淹死就成了領導嘴裡不可避免要付出的代價然後被遺棄。】

具體到`:not`,僅支持單個simple selector意味著可將:not簡單視為一種新的simple selector,從工程師的角度看,可以完全不改動selector引擎的原有設計和實現,實現起來很容易。而支持複雜的:not或者:matches則意味著必須支持一種以前從未有過的嵌套結構,雖然看起來也不是很難,但數據結構、匹配流程、優化演算法很可能全都要改,實際工作量大許多。

此外,selector是有性能要求的。這是為什麼在css3 selector之前沒有任何需要回溯計算的選擇器。:not也存在性能上的問題。不難看出,其內部如果是compound selectors,性能和不帶:not的相同compound selectors並不會有什麼差別。但是如果裡面有combinator,這個複雜度就不好判斷了。所以之前草案一直規定css匹配時,:not、:matches等只能包含compound selectors,只有調用js的selectors api時才支持完整selectors。不過最近的草案去除了大部分限制,只保留了對:has的限制。這應該是瀏覽器廠商的工程師已經完成了對性能影響的評估——這個事情不是光靠嘴巴說說的,一定是需要真的實現出來然後測試驗證的。這也是為什麼這些新的特性不是一蹴而就的。

以上。


Safari 9.1 已經支持大部分 CSS Selectors 4 中的選擇器。 包括題主說的,但過於複雜的選擇器,實際使用會增加 CSS 的複雜度。

&" dw="644" dh="383" class="origin_image zh-lightbox-thumb lazy" w="644" data-original="https://pic3.zhimg.com/8878b8c3ae4bba178e6e368c405cbf12_r.jpg" data-actualsrc="//i1.wp.com/pic3.zhimg.com/50/8878b8c3ae4bba178e6e368c405cbf12_hd.jpg">


推薦閱讀:

985待業半年多,想去做前端,不知道現在還行嗎?
25歲如花的年紀自學前端是明智的選擇么? 這幾天正猶豫要不要辭職,希望知友能給點意見,先行謝過?
花整個大學的時間研究前端好嗎?
如何評價阮一峰關於前端工具變化快的言論?
如何評價WebKit B3 JIT Compiler?

TAG:前端開發 | CSS |