- 浏览: 141225 次
- 性别:
- 来自: 广州
最新评论
-
zfms:
写的不孬,有时间交流一下
Openfire Server presence(在线状态)消息处理流程 -
yangjianzhouctgu:
您好 可以请教您个问题吗
Aptana Ajax库插件---EXT2.0 -
tianlihu:
不错,比较有效解决了问题
IE6中用了float:left之后导致margin-left双倍边距的BUG解决方法 -
mzba520:
我想请问能不能把openfire部署到tomcat中去,就是把 ...
openfire 源代码研究一 (运行环境的搭建) -
eric_hwp:
...
部署Openfire源码
- 在jquery.fn.init()中,我们对这句jQuery(context).find(selector)没有深入去分析,在使用$()时候,大部分时间都是在使用这句来完成功能的。它就是调用CSS Selector到Dom树去查找和相符CSS语法的元素节点(集)。jQuery名字中query的意义就体现在这里。
- 根据符合CSS语法的字符串,它是怎么到DOM文档树去找到符合条件的元素呢?无论怎么解析这个字符串,它总得有调用最原始的函数来完成功能,这些函数是什么?
- 在没有分析Selector源码之前,说来也不会相信功能强大的selector是建立在元素的getElementsByTagName,getElementById直接引用和元素的childNodes firstChild、lastChild、nextSibling、parentNode、previousSibling等间接引用这些函数的使用。
- 在分析源码之前,我们得了解一下CSS selector,它可以粗略分成几类基本的类型:ID选择器(#id),Class选择器(.class),类型(type)选择器(p),Combinators,属性(Attribute)选择器,Pseudo Classes选择器等。这些都是单一的选择器,可以在应用中把它们组合起来,如:div#id, div:last-child。
- 我们先分析一个例子:span[class=’test’],它是属性选择器,我们一般把它做一个整体来理解:在Dom文档树中找到其class等于’test’的且标签为span的元素。这是一步到位,直接从dom文档树查找(select)所需要的元素。
- 其实我们更细一点分析,完成可以把这个字符串拆分成两步走,第一步是根据document.getElementsByTagName(tagName)取得span的元素集,第二步是再根据其class是否等于test来进行判断,把不等于的元素从结果集中去掉。
- 不光是属性选择器,对所有的复合的选择器,都可以根据这种细粒度来拆分选择器,接下来就是分别是每个小部分进行操作。如果这样,我们就能把CSS selector分成两大类,第一类是是选择(selector),从根据给定的selector从Dom树找到相关的元素节点放到结果集中来。第二类是筛选(filter)。在结果集中判断该元素还满足表达式。
- 这样一来,就完全可以JS的原有直接或间接对Dom元素进行引用的方法,如div#id就可以变成先找到div的元素,之后就判断其元素的id是否等于id,如果不等于就从结果集中删除掉。而对于div[id=’bar’]也是一样,可以看出div#id与div[id=’id’]是一样的操作。对于div.class也可以转换到属性中去操作。
- 现在要做的事就分析那些基本选择器是完成选择(selector)还是筛选(filter)的工作。我们把类型选择器,Combinators统一称为元素选择器,其形式如下:*,E F,E~F,E+F,E>F,E/F,E。这些一定是从dom树中选择元素。
- 对于ID选择器和Class选择器,它们也可以在selector字符串的起始位置,说明他们也可以完成选择(selector)功能。当它们不在起始位置上,如div#id,div.class那他们就是筛选器。我们可以变通一下统一起来,对于ID选择器可以采用document.getElementById来直接引用。但是对于.class就不一样了,它没有相对的函数。这种情况下,我们可以把它变成*.class。*能取得一个范围内的所有的元素,然后再进行筛选。这样对于ID选择器,它有专门的函数来处理,是选择(selector)器。对Class选择器,它是筛选器,特殊情况就是对于*标签取到元素集进行筛选。
- 其它如属性(Attribute)选择器,Pseudo Classes都是筛选器,只能附在一个元素或多个元素后面。,特殊情况就是对于*标签取到元素集进行筛选。
- 看一个:div.foo:nth-child(odd)[@foo=bar]#aId > a的例子:
- 第一步:找到div type选择器的所有元素。
- 第二步:在这些元素中找到class为foo的元素。如果没有就根本不要去分析下面的字符。
- 第三步:根据:nth-child(odd)找到元素的子孩子元素为偶数的的元素。进一步筛选了。
- 第四步:找到[],就是属性筛选器了,根据foo属性值bar来判断集合中还有那些满足条件。
- 第五步:在这些元素集合,找到id=aId的元素,进一步筛选。
- 第六步:在这些元素集合中找到所有元素对应的子元素类型为a的所有子元素。
- 结果:我们可以看到,现在元素是子元素的集合。
- 讲完了通版的大道理,接下来就是来看看jQuery是怎么实现的:
- // 搜索所有与指定表达式匹配的元素。这个函数是找出正在处理的元素的后代元素的好方法。
- // 所有搜索都依靠jQuery表达式来完成。这个表达式可以使用CSS1-3的选择器语法来写。
- find : function(selector) {
- var elems = jQuery.map(this, function(elem) {// 找到每个元素的满足的
- return jQuery.find(selector, elem); });
- return this.pushStack(/[^+>] [^+>]/.test(selector) ? jQuery
- .unique(elems) : elems);// 是不是返回不重复的元素?
- },
- 这是jquery.fn.init调用的find方法。它只是完成之本本对象集合中每一个元素都调用jQuery.find(selector, elem)方法,组合成新unique集合后构建新jquery对象。最重要的实质性的工作在jQuery.find(selector, elem)完成:
- find : function(t, context) {
- if (typeof t != "string")return [t];// 快速处理非字符表达式
- if (context && context.nodeType != 1 && context.nodeType != 9)
- return [];// 确保context是DOM元素或document
- context = context || document;// 缺省的context
- // 初始化,ret:result, done:已经完成,last:上一次的t,nodeName:节点名,
- var ret = [context], done = [], last, nodeName;
- //这里就是把复合选择器的字符串从左到右取最小单元的选择进行分析操作
- //分析操作完之后就这个分析过的字符串部分给删除,
- //然后循环分析接下来的剩余的部分。直到字符串为空。
- //这里的最小单元指如#id,~F(+F,>F),.class,[id='xx'],F,:last()之类
- while (t && last != t) {// t存在,且变化
- var r = []; // ret的tempValue
- last = t; // last:上一次的t
- t = jQuery.trim(t);// 去首尾空格
- var foundToken = false, re = quickChild, // 以>开头的regexp
- m = re.exec(t);
- //这一部分处理了>,+,~的元素选择器。当然有的后代,有的兄弟选择的。
- // 首先判断是不是以>开头,因为每次处理都处理都删除分析过的字符串部分
- //这里可以看作是>作为找到tagName元素的子节点们的标记
- if (m) { ①
- nodeName = m[1].toUpperCase();//tagName
- //在结果集中(第一次是默认是给定的context)找到满足的tagName元素的所有子节点。
- //两个循环,第一是对结果集中每个元素进行,第二个是对每个元素中每个子元素节点。
- //找到结果集中所有的元素的所有子元素的集合。
- for (var i = 0;ret[i]; i++)
- for (var c = ret[i].firstChild;c; c = c.nextSibling)
- if (c.nodeType == 1&& (nodeName == "*" ||
- c.nodeName.toUpperCase() == nodeName))
- r.push(c);
- ret = r; // 现在找到的所有元素都是结果集
- t = t.replace(re, "");// remove已经处理过的字符串部分
- //对于E (F,>F,+F etc)的形式,这里跳过后面的代码又回到while处执行。
- //但是在while处之后会把这个空格去掉。好像没有进行操作。这里变化了是ret。
- //无论后面是怎样的最小单元选择器,都是要根据这个个ret中的元素来进行操作。
- //如果是tagName,那么就是转4处执行ret[i].getElementsByTagName().
- //如果是>tagName,就执行1处的代码,其它的省略,
- //可见每个最小单元之后都可以是任意的空格分隔。
- if (t.indexOf(" ") == 0)continue;
- foundToken = true;// 找到标识
- }
- else {// 第二判断是不是以+~开头 ②
- re = /^([>+~])\s*(\w*)/i;
- if ((m = re.exec(t)) != null) {// 以+~开头的
- r = [];
- var merge = {};
- nodeName = m[2].toUpperCase();// 节点名
- m = m[1];// 符号,如+,~
- // 如果selector字符串的匹配+或~(子元素),
- //在结果集中所有元素中找到其兄弟元素节点。
- //不同的+找的是后续的第一个兄弟元素,
- //而~是找到所有的后续的兄弟元素节点。
- //之后把找到的所有的元素放到结果集合中。
- for (var j = 0, rl = ret.length;j < rl; j++) {
- // 把~和+的操作统一在一起进行处理
- var n = (m == "~" || m == "+"
- ? ret[j].nextSibling: ret[j].firstChild);
- for (;n; n = n.nextSibling)
- if (n.nodeType == 1) {// 保证节点是元素类型
- var id = jQuery.data(n);// 为n元素生成全局唯一的id
- if (m == "~" && merge[id])// 保证ret中元素不重复
- break;// nextSibling会循环到第一个节点?
- if (!nodeName|| n.nodeName.toUpperCase() == nodeName) {
- if (m == "~") merge[id] = true;
- r.push(n);
- }// 直接后续兄弟节点,只进行一次操作。
- if (m == "+") break;
- }
- }
- ret = r;// 找到的所有的元素放到结果集合中。
- t = jQuery.trim(t.replace(re, ""));
- foundToken = true;
- }
- }
- // 不是以>~+开头的或者说除去已经分析过的字符,接下来的字符是不是>~+开头
- if (t && !foundToken) { ③
- //这里的意思是在开始的位置找到,号,说明一个selector已经完成了,那么
- //结果集就要存到已经完成的集合中。结果集也应该初如化。
- if (!t.indexOf(",")) { ④
- //说明运行到这里的时候,还是单个selector的字符串分析是刚刚开始
- //因为>~+不可能得到ret[0]元素等于元素的自身。如果等于的话,
- //那就清除出ret,因为接下来就要把ret结果集中的元素存入done中
- if (context == ret[0]) ret.shift();
- done = jQuery.merge(done, ret);// ret的其它元素放入done
- r = ret = [context];// 重新初始化
- t = " " + t.substr(1, t.length); //把,采用空格代替。
- }
- else { ⑤
- // 说明这一个selector部分还没有完成,同时还没有找到元素
- // 或者是 >F的后面用空格来分隔。
- //* qId:^((?:[\w*_-]|\.)+)(#)((?:[\w*_-]|\.)+)
- // * qclass:^([#.]?)((?:[\\w*_-]|\.)*)
- var re2 = quickID;// 如(.)nodeName#idName
- var m = re2.exec(t);// 找到第一个相配的
- if (m) {m = [0, m[2], m[3], m[1]];// m=[0,#,idName,nodeName]}
- else { re2 = quickClass;// #nodeName,.className
- m = re2.exec(t);// m=[all,#,idName]}
- m[2] = m[2].replace(/\\/g, "");// 去除转义字符
- //取数组的最后一个元素,其实就是为了取到是不是为document,
- //因为只有document才有getElementById,为什么不直接采用
- //document呢?难道document的查找会比先根据element.
- //getElementsByTagName找到元素下面的tagname的相符的
- //集合然后采用id属性去判断对比来得更慢吗?不一定?对于大的Dom树,
- //而element的范围又很小的话,可能会慢一些。
- //不过由于这里还要通过属性选择器来进行验证进行验证,一般来说
- //element.getElementsByTagName会快一点。
- var elem = ret[ret.length - 1];
- if (m[1] == "#" && elem && elem.getElementById
- && !jQuery.isXMLDoc(elem)) {
- var oid = elem.getElementById(m[2]);
- // 回测元素的ID的确存在,在IE中会取name属性的值,同时在form 元素中
- // 会选中在form中元素的name属性为id的元素。
- if ((jQuery.browser.msie || jQuery.browser.opera) && oid
- && typeof oid.id == "string" && oid.id != m[2])
- //通过属性选择器来进行验证。
- oid = jQuery('[@id="' + m[2] + '"]', elem)[0];
- // 回测元素的node Name是否相同,如div#foo,可以提交效率
- ret = r = oid && (!m[3] || jQuery.nodeName(oid, m[3]))
- ? [oid]: [];
- }
- else {
- //这里处理了#id,.class tagName,div#id四种形式
- //这里我们还可以看出E F形式。并没有特殊的处理。就是采用了
- //E.getElementsByTagName(F)就可以了。
- //这个就能取后元素的所有后代为F和F的元素节点。
- //和F使用是统一的起来。因为E都是结果集。
- for (var i = 0;ret[i]; i++) {
- //因为m有两种情况:[0,#,idName,nodeName]、[all,#/.,idName/class/tagName]
- //这里就是根据这两种情况来取得tagName,m[1] == "#" && m[3]
- //为真,说明是第一种,取nodeName。如果m[1] == "#" && m[3]为假
- //说明m[1] <> "#"||!m[3],而m[1] != ""说明只能是第二个数组中的.或#
- //说明了对于#nodeName,.className采用element.getElementsByTagName(*).
- //当m[1] == "",说明是一个E 元素选择器,它不带任何的前缀。如:p。这个时候
- //m[2]是tagName.
- //m[0] == "" ,只能指第二个数组中的。它=="",说明没有找到符合qclass的regExp.
- //其它的情况都不会为"",它为"",!m[1],!m[2]也都为true.
- var tag = (m[1] == "#" && m[3] ? m[3] : (m[1] != ""
- || m[0] == "" ? "*" : m[2]));// 分情况取tagName
- //*的情况下,对于object标签转换为param标签进行操作。
- if (tag == "*"&& ret[i].nodeName.toLowerCase() == "object")
- tag = "param";// Handle IE7 being really dumb about <object>s
- //把结果集合中第一个元素的getElementsByTagName存入到临时的结果集中。
- r = jQuery.merge(r, ret[i].getElementsByTagName(tag));
- }
- //class选择器的话,就根据class属性在找到结果集合中过滤
- if (m[1] == ".") r = jQuery.classFilter(r, m[2]); ⑦
- //id选择器的话,就根据id属性在找到结果集合中过滤
- if (m[1] == "#") {
- var tmp = [];
- for (var i = 0;r[i]; i++)
- if (r[i].getAttribute("id") == m[2]) {
- tmp = [r[i]];
- break;
- }
- r = tmp;
- }
- ret = r;
- }
- t = t.replace(re2, "");
- }
- }
- //这个时候已经找到结果的集合,对于如CSS Selector为:hidden的属性筛选器,
- //它的集合就是context的下面的所有元素节点。也就是说上面的
- //代码无论如何都能找到元素的集合。这个集合可能是>/+~ F
- //或#id,.class tagName,div#id,对于不满足这些条件的,就采用
- //context.getElementsByTagName(*)要取得其下所有的元素
- //确保接下来的过滤(筛选)
- if (t) {// 根据余下的selector,对找到的r集合中的元素进行过滤 ⑥
- var val = jQuery.filter(t, r); ⑧
- ret = r = val.r;
- t = jQuery.trim(val.t);// 去首尾空格
- }
- }
- //如果还会有t存在说明一个问题:last == t
- //也就是上一次的过程中没有进行成功的解析一个最小单元的选择器
- //原因是输入的 t 字符串有语法上的错误。如果是采用,分隔的多选择器
- //那么就是当前及之后的选择器不分析。完成的done就是之前的结果集。
- //觉得这样处理不好,很多时间我们都会写错CSS selectror,不报错,
- //对于调试发现问题特难。
- if (t) ret = [];
- //出现这种情况说明运行到这里的时候,还是单个selector的字符串分析是刚刚开始
- //如果等于的话,那就清除出ret,因为接下来就要把ret结果集中的元素存入done中
- if (ret && context == ret[0])
- ret.shift();// 去掉根上下文
- done = jQuery.merge(done, ret);// 合并
- return done;
- },
- 上面find的实现的代码有点长。其实分析起来也不是很难。①②③④⑤处两个if-else是元素选择器,针对>/+~ F或#id,.class tagName,div#id这样的选择器进行查找元素,构成结果集。⑥实现的就是分析它之后的属性选择器进行筛选。这段代码说白就是select与Filte之间的交互分析CSS selector的字符串进行查找或筛选的过程。
- 具体的细节在代码中有分析。在⑦处它采用先找到所有元素然后对每个元素进行class的判断来分析如.class这样selector。因为它在起始位说明是查找器。但是这里对这个最小的单元部分,我们还可能两个部分,找到所有元素,然后一个个排查,排查就是采用了jQuery.classFilter(r, m[2]):
- classFilter : function(r, m, not) {
- m = " " + m + " ";//这里的做法就是怕出现如”class12”这样的问题
- var tmp = []; //如果传的m= class1,这个的条件是满足的,实际是不。
- for (var i = 0;r[i]; i++) {
- var pass = (" " + r[i].className + " ").indexOf(m) >= 0;
- if (!not && pass || not && !pass)
- tmp.push(r[i]);
- }
- return tmp;
- },
- jQuery.classFilter是比较简单。在find()的第二个部分是筛选,它调用jQuery.filter(t, r)来完成功能:
- //根据CSS selector表达式查找集合中满足该表达式的所有元素
- //还可以根据not来指定不满足CSS selector表达式元素集
- filter : function(t, r, not) {
- var last;
- while (t && t != last) {// t存在,且改变
- last = t;
- // Match: [@value='test'], [@foo]
- // 1、^(\[) *@?([\w:-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/,
- // Match: :contains('foo')
- // 2、^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/,
- // Match: :even, :last-child, #id, .class
- // 3、new RegExp("^([:.#]*)(" + chars + "+)")],
- //这里可以看出我们直接调用filter的时候的selector如不是筛选器的话,
- //那就不进行筛选了,这里的selector语法如[@value='test'], [@foo]、
- //:contains('foo'),:even, :last-child, #id, .class的形式
- //可以是上面这几种形式的组合,但不能包括元素选择器。
发表评论
-
flex 电子书籍下载
2009-11-25 17:12 2144http://wmcai.blog.163.com/blog/ ... -
基于servlet导出Flex/Flash界面为图形文件的简单方法
2009-07-31 14:12 1655关键字: flex,chart,java 使用fl ... -
Flex 3的本地化应用
2009-07-20 13:30 1558这两天看了一下Flex 3的 ... -
FLEX组件的生命周期
2009-05-22 14:42 1648组件实例化生命周期描述了用组件类创建组件对象时所发生的一系列步 ... -
Flex性能优化之cpu占用率
2009-05-08 10:39 4830先扯几句,team中有一个正在试运行的项目,最近被客户打了 ... -
Understanding garbage collection in Flash Player 9
2009-05-06 19:19 1196原文 Understanding garbage ... -
关于firefox文本折行的问题
2009-04-13 14:57 1593一直有传说这个是firefox的一个bug,属于无法完美解决的 ... -
Adobekit教你如何修改FLASH右键菜单
2009-04-07 10:32 4904有些东西只有用到了才 ... -
CSS IE7 IE6 Firefox多浏览器兼容-著名的星号* Html Hack(招数)[z]
2009-04-01 10:08 2878From: [url]http://www.keephelp. ... -
Flex上载和下载文件
2009-01-20 14:28 5689示例:上载和下载文件 FileIO 示例说明了在 Flash ... -
Flex 2 中的元数据标签
2009-01-19 16:33 906原文作者:Rich Tretola(作者是everything ... -
理解ClassLoader机制
2009-01-18 23:09 1221当JVM(Java虚拟机)启动时,会形成由三个类加载器组成的初 ... -
一个简易实用的web权限管理模块的应用与实现
2009-01-18 21:59 1401本文介绍一个简易实用的web权限管理模块的应用与实现。 ... -
JS中Null与Undefined的区别
2009-01-04 17:40 2353在JavaScript中存在这样两种原始类型:Null与Und ... -
Flex3 framework RSL机制介绍
2008-12-25 17:45 2397阻碍Flex应用的一个很大因素就是采用Flex框架的程序体积非 ... -
IE6中用了float:left之后导致margin-left双倍边距的BUG解决方法
2008-12-22 17:17 5033先看css代码: div { float:left; ... -
Adobe Meermeer:跨浏览器网页测试工具
2008-12-09 09:24 1664每年Adobe公司都会有一个最具吸引力的项目,在2007年的会 ... -
网站性能优化
2008-12-03 17:59 972/** *作者:张荣华 *日期:2008-12-01 **/ ... -
openfire 源代码研究一 (运行环境的搭建)
2008-11-30 21:31 3320关于Openfire的介绍在此不多说了,网上有很多关于这个基于 ... -
FLEX3中应用CSS完全详解手册!
2008-11-21 14:13 1820编辑完这个FLEX下的CSS说明后,我基本已经兵临崩溃边缘了。 ...
相关推荐
《jQuery源码分析》 jQuery,作为一款广泛使用的JavaScript库,极大地简化了DOM操作、事件处理、动画制作以及Ajax交互。深入理解其源码对于提升JavaScript编程技能和优化前端性能至关重要。本文将从核心概念、设计...
### jQuery源码分析 #### 一、概述 jQuery作为一个卓越的JavaScript库,以其简洁高效的特性在前端开发领域占据了一席之地。与Prototype、YUI、Mootools等其他JavaScript库相比,jQuery更加注重实用性,去除了一些...
这份中文注释的源码分析旨在帮助开发者逐步揭开jQuery的神秘面纱,提升JavaScript编程技能。 首先,jQuery的核心在于选择器引擎Sizzle。Sizzle是一个高效的选择器解析器,能够处理CSS1至CSS3的选择器,包括ID、类、...
《jQuery源码深度剖析》 jQuery,作为一款广泛使用的JavaScript库,它的源码设计和实现方式一直是许多开发者学习和研究的重点。本分析基于jQuery 1.2.6版本,这个版本虽然相对较老,但其中蕴含的设计思想和核心原理...
接着,源码分析揭示了 init 函数的实现逻辑。函数首先检查是否有 selector 参数传入,如果没有,那么就返回 this,即一个空的 jQuery 对象。如果 selector 是字符串,则根据字符串的类型和内容,进行不同处理。对于 ...
### JQuery源码的奥秘逐行分析视频教程 #### JQuery简介 JQuery 是一款轻量级的 JavaScript 库,它极大地简化了 HTML 文档遍历、事件处理、动画以及 Ajax 交互等操作。JQuery 提供了一个简洁且强大的 API 接口,...
7. **源码结构分析**:jQuery源码采用模块化设计,分为核心、选择器、遍历、DOM操作等多个部分。理解其模块划分和依赖关系,有助于我们更好地理解代码结构和逻辑。 8. **学习资源**:除了这份源码解读,还有其他...
《jQuery 源码分析——揭示JavaScript库的精髓》 jQuery,这个JavaScript库自2006年诞生以来,就以其简洁的API和强大的功能深受开发者喜爱,它极大地简化了DOM操作、事件处理、动画效果以及Ajax交互。本文将深入...
**jQuery 1.2.6 源码分析** jQuery 是一个广泛使用的 JavaScript 库,它简化了 HTML 文档遍历、事件处理、动画以及 Ajax 交互等任务。本篇文章将深入探讨 jQuery 1.2.6 版本的源码,揭示其背后的实现原理,帮助...
《jQuery源码分析》 jQuery,作为一款广泛使用的JavaScript库,极大地简化了DOM操作、事件处理、动画设计和Ajax交互。对于开发者来说,深入理解jQuery的源码不仅可以提升编程技能,还能帮助我们优化代码,提高网页...
《jQuery 1.4.3 源码分析——核心部分》 jQuery 是一个广泛使用的JavaScript库,它极大地简化了JavaScript的DOM操作、事件处理、动画制作和Ajax交互。在jQuery 1.4.3版本中,其核心部分主要包括选择器引擎、DOM操作...
提供的压缩包文件名列表与Jquery源码分析的主题不相符,它们看起来是音频文件的名称,可能是相声或者音乐作品。然而,你要求的是关于Jquery的源码分析。因此,我将专注于Jquery这个JavaScript库的相关知识点。 **...
1. **模块化设计**:jQuery源码采用模块化设计,分为多个部分,如`selector.js`(选择器引擎)、`core.js`(核心功能)、`traversing.js`(遍历DOM)等,这有利于代码的组织和维护。 2. **函数封装**:jQuery将所有...
《jQuery 1.2.6 源码分析》 jQuery是JavaScript库的典范,以其简洁的API和强大的功能赢得了开发者们的广泛喜爱。在1.2.6版本中,jQuery的核心特性已经相当成熟,它提供了丰富的DOM操作、事件处理、动画效果以及Ajax...
在本文中,我们将通过对jQuery源码的核心部分进行分析,深入理解其工作原理和设计模式。 首先,jQuery 是一个函数,通常用 `$` 符号表示。当你调用这个函数,例如 `$(‘name_input’).val()`,它会执行函数内的逻辑...
**jQuery 源码分析** jQuery 是一个广泛使用的 JavaScript 库,它极大地简化了 DOM 操作、事件处理、动画效果以及Ajax交互等任务。在深入分析 jQuery 1.2.6 的源码时,我们可以了解到这个早期版本的核心设计原则和...
源码分析可以让我们理解jQuery如何使用CSS属性和时间函数实现平滑的动画效果。 7. **插件扩展机制** jQuery的插件系统是其灵活性的关键。通过研究`$.fn.extend()`和`$.extend()`,我们可以学习如何编写自己的...