sizzle受歡迎的原因有以下幾點:
1.幾乎支持大部分的css,還支持CSS3新的屬性,同時又很高效。
一般選擇器的匹配模式(包括老版本的jQuery),都是一個順序的思維方式:
在需要遞進(jìn)式匹配時,比如$("div a") 這樣的匹配時,執(zhí)行的操縱都是先匹配頁面中div然后再匹配它的節(jié)點下的a標(biāo)簽,之后返回結(jié)果。我們知道CSS的匹配規(guī)則是從右邊向左篩選,jQuery在Sizzle中延續(xù)了這樣的算法,先搜尋頁面中所有的a標(biāo)簽,在之后的操縱中再往后判定它的父節(jié)點(包括父節(jié)點以上)是否為div,一層一層往上過濾,最后返回該操縱序列。
sizzle只能說是大體如此,此外在1.8中引入了編譯的概念,大大提高了重復(fù)的選擇的效率。
瀏覽器渲染原理:
瀏覽器從下載文檔到顯示頁面的過程是個復(fù)雜的過程,這里包含了重繪和重排。各家瀏覽器引擎的工作原理略有差別,但也有一定規(guī)則。
簡單講,通常在文檔初次加載時,瀏覽器引擎會解析HTML文檔來構(gòu)建DOM樹,之后根據(jù)DOM元素的幾何屬性構(gòu)建一棵用于渲染的樹。渲染樹的每個節(jié)點都有大小和邊距等屬性,類似于盒子模型(由于隱藏元素不需要顯示,渲染樹中并不包含DOM樹中隱藏的元素)。
當(dāng)渲染樹構(gòu)建完成后,瀏覽器就可以將元素放置到正確的位置了,再根據(jù)渲染樹節(jié)點的樣式屬性繪制出頁面。由于瀏覽器的流布局,對渲染樹的計算通常只需要遍歷一次就可以完成,所以我們知道瀏覽器最終會將HTML文檔(或者說頁面)解析成一棵DOM樹,如下代碼將會翻譯成以下的DOM:
<div id="text"> <p> <input type="text" /> </p> <div class="aaron"> <input type="checkbox" name="readme" /> <input type="checkbox" name="ttt" /> <input type="checkbox" name="aaa" /> <p>Sizzle</p> </div> </div>
如果想要操作到當(dāng)中那個checkbox,我們需要有一種表述方式,使得通過這個表達(dá)式讓瀏覽器知道我們是想要操作哪個DOM節(jié)點。
這個表述方式就是CSS選擇器,它是這樣表示的:
div > p + .aaron input[type="checkbox"]
表達(dá)的意思是:div底下的p的兄弟節(jié)點,該節(jié)點的class為aaron ,并且其屬性type為checkbox。
常見的選擇器:
#test
表示id為test的DOM節(jié)點.aaron
表示class為aaron的DOM節(jié)點input
表示節(jié)點名為input的DOM節(jié)點div > p
表示div底下的p的DOM節(jié)點div + p
表示div的兄弟DOM節(jié)點p
其實最終都是通過瀏覽器提供的接口實現(xiàn)的,由于低級瀏覽器并未提供這些高級點的接口,所以才有了Sizzle這個CSS選擇器引擎。Sizzle引擎提供的接口跟document.querySelectorAll是一樣的,其輸入是一串選擇器字符串,輸出則是一個符合這個選擇器規(guī)則的DOM節(jié)點列表,因此第一步驟是要分析這個輸入的選擇器。
通過sizzle與高級API獲取的結(jié)果是一致的:
$('div > div.aaron input[name=ttt]') document.querySelectorAll(' div > div.aaron input[name=ttt]')
這個是相對復(fù)雜的CSS的組合了,涉及到了幾種不同類型的選擇器,除去querySelectorAll這種高級API,我們是無法直接獲取到對應(yīng)的節(jié)點引用的,因為Sizzle要實現(xiàn)這種查找也是非常復(fù)雜的,這里面就要涉及一系列的概念。
1.拆分選擇器,把每一個選擇器組成能夠處理的最小化單元。
div.aaron
這行代碼原生的API不認(rèn)識,但是div與.aaron都是有API能直接獲取到的,所以拆分出后提供后面進(jìn)行關(guān)聯(lián)匹配篩選等等。這里sizzle就引入了詞法分析器與種子合集。
2.Sizzle也是遵循從右到左開始查找,但是不僅僅是這樣。
瀏覽器提供的查找接口,基本靠譜的就只有三個:
Expr.find = { 'ID' : context.getElementById, 'CLASS' : context.getElementsByClassName, 'TAG' : context.getElementsByTagName }
所以我們開始第一查找,從右到左邊依次取出最小的單元選擇器,通過ID、CLASS.TAG去查找,如果能找到就放到結(jié)果集中,這樣第一時間定位到了最終的元素必須會存在的合集。
3.這樣只能找出可能存在的合集,但是沒有精確到具體的選擇器上,所以還需要一個篩選的過程,這個過程也是最復(fù)雜的。
Sizzle從1.8后引入的“編譯”的概念,用于提高性能。
請驗證,完成請求
由于請求次數(shù)過多,請先驗證,完成再次請求
打開微信掃碼自動綁定
綁定后可得到
使用 Ctrl+D 可將課程添加到書簽
舉報