-
课前(JQuery的基础运用、API的熟悉度、JavaScript\DOM\CSS\常见的设计模式、数据结构)。。。。。。依赖模块(回调函数、异步加载、数据缓存、动画队列)。。。。。。整体分析(选择器、DOM处理、事件、AJAX、动画模块)查看全部
-
index.html中代码思路分析: 首先说两个关键点: 1. 最终生成的compile中的matcher函数是 elementMatcher返回的函数。elementMatcher的形参matchers为一个有两个函数元素的数组。 2. elementMatcher返回的函数执行时,i是从最大值开始的。 拆分: elementMatcher的形参matchers数组元素(这里闭包用的出神入化): matchers[0]: 为addCombinator包装的(用来查找parentNode的)filter.TAG再次包装后返回的函数 matchers[1]: 为filter.ATTR包装后返回的函数 总结: 1、所以过滤流程为 --> 传入ele后会先根据matchers[1]查看元素是否有[name=ttt], 然后根据matchers[0]查看ele的祖先是否有元素名为Aaron的元素。 2、compile中的matcher函数就是用空间换时间的编译函数。查看全部
-
matcherFromTokens,它充当了selector“分词”与Expr中定义的匹配方法的串联与纽带的作用。Sizzle巧妙的就是它没有直接将拿到的“分词”结果与Expr中的方法逐个匹配逐个执行,而是先根据规则组合出一个大的匹配方法,最后一步执行。 如果遇到关系选择符就会合并分组了 matchers = [addCombinator(elementMatcher(matchers), matcher)];查看全部
-
注意:下边为index.html的注释,没有写头部,自己补全后可以合并到一起查阅。这个例子写的非常好!!! 查看【同学代码】中,我提交的代码也可以看到注释~ <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) { // 递归出可以处理的元素再进行操作 //找到第一个亲密的节点,立马就用终极匹配器判断这个节点是否符合前面的规则 return matcher(elem); } } } }查看全部
-
function elementMatcher(matchers) { // 上边filter为最小处理单元,这里为基于最小单元组合的集中处理站 return matchers.length > 1 ? function(elem, context, xml) { var i = matchers.length; while (i--) { // 对每个种子(seed)元素尝试匹配selector,matchers是为selector定制的有序匹配数组,若按照数组顺序都能匹配上,就匹配成功,否则失败 if (!matchers[i](elem, context, xml)) { return false; } } return true; } : //单个匹配器的话就返回自己即可 matchers[0]; // 这个也是个函数,为上边filter中的某一个 } 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引入这个编译函数主要的作用是为分词的筛选,提高逐个匹配的效率,实现闭包缓存 闭包是js的特性,我们经常会用来作为私有变量的保存处理,那么sizzle就很好的利用了这一特性,把选择器中每一个选择原子都变成了函数的处理方法,然后通过闭包保存着。再缓存在内存中去,这样有重复使用的时候就会首先调用缓存。查看全部
-
所以sizzle从1.8后采用了空间换时间的方式,通过把各种过滤器编译成闭包的函数,所以这个过程也可说是"编译函数"。-- 看左边下边代码,看来闭包是可以空间换时间的啊查看全部
-
* 假设初始的selector为:var selector = 'div.aaron input[name=ttt]'; * 经过上边执行后可能就变为:div.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 这里就是一个上边定义的函数 if ((seed = find(token.matches[0]))) { match.splice(i, 1); // 删除match上边使用过的那一项 selector = seed.length && toSelector(match); // 这里的match是新生成的match数组,selector为根据新的match新拼接出来的选择器 results.push(seed); // seed为Expr中的find根据参数匹配的结果 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 直接调用querySelectorAll 2、否则,降级通过sizzle处理,那么内部会有一个规则把选择器分组groups,然后通过从右边往左边查找,加入编译函数的方式节约重复查找的性能问题查看全部
-
jQuery查询(构造)的对象主要是dom元素,结果可能是单一元素,也可能是合集。 当然啦,根据API,jQuery构建的不仅仅只是DOM元素,还有 布尔值为false的值、HTML字符串、$(function(){}) 等等…查看全部
-
querySelector和querySelectorAll是W3C提供的新的查询接口 目前 IE8/9及Firefox/Chrome/Safari/Opera 的最新版已经支持它们。 但是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查看全部
-
理解下边的注释,为下一节做准备: $('#test1').click(function() { var aaRoot = document.getElementById('aaronId'); var element = aaRoot.querySelector('.aaron'); alert(element); // 结果为null,说明querySelector不能选择自己 }) //通过一个上下文查找 $('#test2').click(function() { var aaRoot = document.getElementById('aaronId'); var element = aaRoot.querySelector('.aaron span'); alert(element); // querySelector结果为一个element }) //直接查找 $('#test3').click(function() { var elementList = document.querySelectorAll('.aaron span'); alert(elementList); // querySelectorAll结果为一个list,所以在使用上更符合jquery一些 })查看全部
-
排版引擎解析 CSS 选择器时一定要从右往左解析。 要知道DOM树是一个什么样的结构,一个元素可能有若干子元素,如果每一个都去判断一下显然性能太差。而一个子元素只有一个父元素,所以找起来非常方便。你可以看看CSS的选择器的设计,完全是为了优化从子元素找父元素而决定的。 打个比如 p span.showing 你认为从一个p元素下面找到所有的span元素并判断是否有class showing快,还是找到所有的span元素判断是否有class showing并且包括一个p父元素快 ? 同时我们也能够看出,在选择器结尾加上「*」就大大降低了这种优势,这也就是很多优化原则提到的尽量避免在选择器末尾添加通配符的原因。查看全部
举报
0/150
提交
取消