-
課前(JQuery的基礎(chǔ)運用、API的熟悉度、JavaScript\DOM\CSS\常見的設(shè)計模式、數(shù)據(jù)結(jié)構(gòu))。。。。。。依賴模塊(回調(diào)函數(shù)、異步加載、數(shù)據(jù)緩存、動畫隊列)。。。。。。整體分析(選擇器、DOM處理、事件、AJAX、動畫模塊)查看全部
-
index.html中代碼思路分析: 首先說兩個關(guān)鍵點: 1. 最終生成的compile中的matcher函數(shù)是 elementMatcher返回的函數(shù)。elementMatcher的形參matchers為一個有兩個函數(shù)元素的數(shù)組。 2. elementMatcher返回的函數(shù)執(zhí)行時,i是從最大值開始的。 拆分: elementMatcher的形參matchers數(shù)組元素(這里閉包用的出神入化): matchers[0]: 為addCombinator包裝的(用來查找parentNode的)filter.TAG再次包裝后返回的函數(shù) matchers[1]: 為filter.ATTR包裝后返回的函數(shù) 總結(jié): 1、所以過濾流程為 --> 傳入ele后會先根據(jù)matchers[1]查看元素是否有[name=ttt], 然后根據(jù)matchers[0]查看ele的祖先是否有元素名為Aaron的元素。 2、compile中的matcher函數(shù)就是用空間換時間的編譯函數(shù)。查看全部
-
matcherFromTokens,它充當了selector“分詞”與Expr中定義的匹配方法的串聯(lián)與紐帶的作用。Sizzle巧妙的就是它沒有直接將拿到的“分詞”結(jié)果與Expr中的方法逐個匹配逐個執(zhí)行,而是先根據(jù)規(guī)則組合出一個大的匹配方法,最后一步執(zhí)行。 如果遇到關(guān)系選擇符就會合并分組了 matchers = [addCombinator(elementMatcher(matchers), matcher)];查看全部
-
注意:下邊為index.html的注釋,沒有寫頭部,自己補全后可以合并到一起查閱。這個例子寫的非常好?。?! 查看【同學(xué)代碼】中,我提交的代碼也可以看到注釋~ <body> <button id="test1">模擬編譯原理,點擊選中checked</button> <div id="text"> <div class="Aaron"> <input type="checkbox" name="readme" /> <input type="checkbox" name="ttt" /> <input type="checkbox" name="aaa" /> <p>Sizzle</p> </div> </div> <script type="text/javascript"> var filter = { ATTR: function(name, operator,check) { return function(elem) { var attr = elem.getAttribute(name) if (operator === "=") { if(attr === check){ return true } } return false; } }, TAG: function(nodeNameSelector) { return function(elem) { return elem.nodeName && elem.nodeName.toLowerCase() === nodeNameSelector; }; } } function addCombinator(matcher) { return function(elem, context, xml) { while ((elem = elem['parentNode'])) { if (elem.nodeType === 1) { // 遞歸出可以處理的元素再進行操作 //找到第一個親密的節(jié)點,立馬就用終極匹配器判斷這個節(jié)點是否符合前面的規(guī)則 return matcher(elem); } } } }查看全部
-
function elementMatcher(matchers) { // 上邊f(xié)ilter為最小處理單元,這里為基于最小單元組合的集中處理站 return matchers.length > 1 ? function(elem, context, xml) { var i = matchers.length; while (i--) { // 對每個種子(seed)元素嘗試匹配selector,matchers是為selector定制的有序匹配數(shù)組,若按照數(shù)組順序都能匹配上,就匹配成功,否則失敗 if (!matchers[i](elem, context, xml)) { return false; } } return true; } : //單個匹配器的話就返回自己即可 matchers[0]; // 這個也是個函數(shù),為上邊f(xié)ilter中的某一個 } function matcherFromTokens(tokens){ var len = tokens.length; var matcher, matchers = []; for (i = 0; i < len; i++) { if (tokens[i].type === " ") { // 如果是空元素,首先要查到非空元素,然后再作處理 matchers = [addCombinator(elementMatcher(matchers), matcher)]; } else { matcher = filter[tokens[i].type].apply(null, tokens[i].matches); matchers.push(matcher); } } return elementMatcher(matchers); }查看全部
-
function compile() { //種子合集 var seed = document.querySelectorAll('input') //選擇器 var selector = "Aaron [name=ttt]"; var elementMatchers = []; var results = [] var match = [{ matches: ["div"], type: "TAG", value: "Aaron" }, { type: " ", value: " " }, { matches: ["name", "=", "ttt"], type: "ATTR", value: "[name=ttt]" }] elementMatchers.push(matcherFromTokens(match)); var matcher, elem; for (var i = 0; i < seed.length; i++) { matcher = elementMatchers[0]; var elem = seed[i]; if (matcher(elem)) { results.push(elem); break; } } results[0].checked = 'checked' } $('#test1').click(function() { compile(); }) </script> </body> </html>查看全部
-
那么sizzle從給1.8開始就引入了編譯的概念: sizzle引入這個編譯函數(shù)主要的作用是為分詞的篩選,提高逐個匹配的效率,實現(xiàn)閉包緩存 閉包是js的特性,我們經(jīng)常會用來作為私有變量的保存處理,那么sizzle就很好的利用了這一特性,把選擇器中每一個選擇原子都變成了函數(shù)的處理方法,然后通過閉包保存著。再緩存在內(nèi)存中去,這樣有重復(fù)使用的時候就會首先調(diào)用緩存。查看全部
-
所以sizzle從1.8后采用了空間換時間的方式,通過把各種過濾器編譯成閉包的函數(shù),所以這個過程也可說是"編譯函數(shù)"。-- 看左邊下邊代碼,看來閉包是可以空間換時間的啊查看全部
-
* 假設(shè)初始的selector為:var selector = 'div.aaron input[name=ttt]'; * 經(jīng)過上邊執(zhí)行后可能就變?yōu)椋篸iv.aaron [name=ttt],少了input * results為過濾出來的input元素集合查看全部
-
$('button').click(function(){ var results = []; var i = match.length // 4 while (i--) { /** token eg: matches: ["name"] type: "ATTR" value: "[name=ttt]" */ token = match[i]; if (Expr.relative[(type = token.type)]) { //eg. type == "ATTR" break; } if ((find = Expr.find[type])) { // find 這里就是一個上邊定義的函數(shù) if ((seed = find(token.matches[0]))) { match.splice(i, 1); // 刪除match上邊使用過的那一項 selector = seed.length && toSelector(match); // 這里的match是新生成的match數(shù)組,selector為根據(jù)新的match新拼接出來的選擇器 results.push(seed); // seed為Expr中的find根據(jù)參數(shù)匹配的結(jié)果 break; } } } alert('選擇器 '+selector) // eg. div.aaron [name=ttt] 可以和上邊初始的selector做下比較 alert('seed種子合集 '+results[0]) // eg. HTMLCollection(6) [input, input, input, input, input, input, readme: input, ttt: input, aaa: input] console.log('seed種子', results); })查看全部
-
1、如果瀏覽器支持高級API 直接調(diào)用querySelectorAll 2、否則,降級通過sizzle處理,那么內(nèi)部會有一個規(guī)則把選擇器分組groups,然后通過從右邊往左邊查找,加入編譯函數(shù)的方式節(jié)約重復(fù)查找的性能問題查看全部
-
jQuery查詢(構(gòu)造)的對象主要是dom元素,結(jié)果可能是單一元素,也可能是合集。 當然啦,根據(jù)API,jQuery構(gòu)建的不僅僅只是DOM元素,還有 布爾值為false的值、HTML字符串、$(function(){}) 等等…查看全部
-
querySelector和querySelectorAll是W3C提供的新的查詢接口 目前 IE8/9及Firefox/Chrome/Safari/Opera 的最新版已經(jīng)支持它們。 但是Element.querySelectorAll有個bug <div> <div id="bar"> <span> <a href="###">asfd</a> </span> </div> </div> var bar = document.getElementById('bar'); console.log(bar.querySelectorAll('div span a').length); // 1 console.log(bar.querySelectorAll('span a').length); // 1 console.log($('div span a',bar)); // jQuery沒有選擇到 解決這個問題的方法就是在context對象(本例即bar)上添加一個Id,然后變成如下的選擇。(其中id后邊是有空格的,這樣如果第一個選擇器是從context開始的就選不到context自身了,選擇器只能選擇context的子) console.log(bar.querySelectorAll('[id="XXX"] div span a').length); // 1 console.log(bar.querySelectorAll('[id="XXX"] span a').length); // 1查看全部
-
理解下邊的注釋,為下一節(jié)做準備: $('#test1').click(function() { var aaRoot = document.getElementById('aaronId'); var element = aaRoot.querySelector('.aaron'); alert(element); // 結(jié)果為null,說明querySelector不能選擇自己 }) //通過一個上下文查找 $('#test2').click(function() { var aaRoot = document.getElementById('aaronId'); var element = aaRoot.querySelector('.aaron span'); alert(element); // querySelector結(jié)果為一個element }) //直接查找 $('#test3').click(function() { var elementList = document.querySelectorAll('.aaron span'); alert(elementList); // querySelectorAll結(jié)果為一個list,所以在使用上更符合jquery一些 })查看全部
-
排版引擎解析 CSS 選擇器時一定要從右往左解析。 要知道DOM樹是一個什么樣的結(jié)構(gòu),一個元素可能有若干子元素,如果每一個都去判斷一下顯然性能太差。而一個子元素只有一個父元素,所以找起來非常方便。你可以看看CSS的選擇器的設(shè)計,完全是為了優(yōu)化從子元素找父元素而決定的。 打個比如 p span.showing 你認為從一個p元素下面找到所有的span元素并判斷是否有class showing快,還是找到所有的span元素判斷是否有class showing并且包括一個p父元素快 ? 同時我們也能夠看出,在選擇器結(jié)尾加上「*」就大大降低了這種優(yōu)勢,這也就是很多優(yōu)化原則提到的盡量避免在選擇器末尾添加通配符的原因。查看全部
舉報
0/150
提交
取消