Your SlideShare is downloading. ×
0
jQuery源码学习
jQuery源码学习
jQuery源码学习
jQuery源码学习
jQuery源码学习
jQuery源码学习
jQuery源码学习
jQuery源码学习
jQuery源码学习
jQuery源码学习
jQuery源码学习
jQuery源码学习
jQuery源码学习
jQuery源码学习
jQuery源码学习
jQuery源码学习
jQuery源码学习
jQuery源码学习
jQuery源码学习
jQuery源码学习
jQuery源码学习
jQuery源码学习
jQuery源码学习
jQuery源码学习
jQuery源码学习
jQuery源码学习
jQuery源码学习
jQuery源码学习
jQuery源码学习
jQuery源码学习
jQuery源码学习
jQuery源码学习
jQuery源码学习
jQuery源码学习
jQuery源码学习
jQuery源码学习
jQuery源码学习
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

jQuery源码学习

1,952

Published on

0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
1,952
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
20
Comments
0
Likes
1
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. jQuery源码学习<br />qijun.weiqj<br />
  • 2. 大纲<br />jQuery无架构*<br />常用的静态方法<br />解密万能构造器*<br />理解jQuery对象*<br />深入事件处理*<br />
  • 3. jQuery无架构<br />源码之前,了无秘密<br />
  • 4. varjQuery = function(selector, context) {<br />};<br />jQuery.extend = function(target, source) {<br /> // 回忆FD.common.apply<br />};<br />于是我们有了静态方法 $.extend(… <br />因为函数也是对象<br />
  • 5. 接着我们就可以扩展静态方法:<br />$.extendIf = function(target, src) {<br />}<br />// 注:丹侠在fdev4中提供了此方法,以此眷顾我们的fdev3<br />当然也可以这样<br />$.extend($, {<br />extendIf: function() {<br /> …<br /> }<br /> add: function() {<br /> …<br /> }<br />})<br />
  • 6. 可以更专业:<br />$.extend({<br />extendIf: function()…<br /> add: function()…<br />})<br />因为可以省略第一个参数, 此时target就是this, 即jQuery<br />在这里我们初步感觉到jQueryAPI的特点:<br />精简、灵活、还很智能, jQuery的流行最大的原因就在于此<br />jQuery中所有静态方法就是这样扩展的<br />注:但是我们把扩展jQuery的大任交给fdev-4维护小组,以避免名字空间冲突。应用中一般情况下不允许扩展jQuery对象<br />
  • 7. 摘录:<br />jQuery.extend({<br />noConflict: function(deep) {<br />isFunction: function( obj ) {<br /> return jQuery.type(obj) === "function";<br /> },<br />isArray: Array.isArray || function( obj ) {<br /> return jQuery.type(obj) === "array";<br /> },<br />isWindow: function( obj ) {<br /> return obj && typeofobj === "object" && "setInterval" in obj;<br /> },<br />isNaN: function( obj ) {<br /> return obj == null || !rdigit.test( obj ) || isNaN( obj );<br /> },<br />
  • 8. 在jQuery中,我们可以这样:<br />$(‘#div’).addClass(‘error’);<br />$(‘ul.tabs’, elm).eq(0).click();<br />从上面我们知道 jQuery是一个函数, 从这里我们知道<br />函数返回值是一个对象,并且有很多的实例方法, 这些方法用来操作相关节点<br />
  • 9. varjQuery = function() {<br /> return new jQuery.fn.init(selector, context);<br />};<br />jQuery.fn = { };<br />jQuery.fn.init = function() {<br />};<br />jQuery.fn.init.prototype {<br />addClass: function() {<br /> },<br />removeClass: function() {<br /> }<br />};<br />从现在开始,我们的jQuery对象也有了addClass和removeClass方法<br />
  • 10. 重构一下:<br />varjQuery = function() {<br /> return new jQuery.fn.init(selector, context);<br />}<br />jQuery.fn = {<br /> init: function() {<br /> },<br />addClass: function() {},<br />removeClass: function() {}<br />}<br />jQuery.fn.init.prototype = jQuery.fn<br />
  • 11. 现在我们就可以扩展jQuery实例方法了<br />$.fn.ajax = function(url, options) {<br />}<br />专业点:<br />$.extend($.fn, {<br /> get: function()…<br /> post: function()…<br />})<br />更专业<br />$.fn.extend({<br /> bind: function() {…}<br />})<br />因为:$.fn.extend = $.extend = function(…, <br />
  • 12. 关于链式调用<br />$.fn.extend({<br />addClass: function() {<br /> …<br /> return this;<br /> }<br />toogleClass: function() {<br /> …<br /> return this;<br /> }<br />hasClass: function() {<br /> return true|false;<br /> }<br />
  • 13. 经验建议<br />为了增加可读性, 避免不同类型API之间的链试调用<br />var elm = $(‘#id’); //为了增加可读性, 避免过多的$, 只在合适的地方使用$构造<br />elm.removeClass(‘error’).addClass(‘success’);<br />elm.click(function() {<br /> …<br />});<br />
  • 14. 轻松一下:浏览一下常用静态方法<br />工具方法<br />$.noConflict // 由fdev-v4 默认调用,以兼容fdev-v3 所以应用中使用jQuery应该在一个closure中<br />$.trim<br />$.each —— 可以对对象和数组进行迭代<br />$.extend —— FD.common.apply / YAHOO.lang.augmentObject<br />$.extendIf<br />$.grep —— <br />$.map<br />$.now —— new Date().getTime(), 方便加时间戳<br />
  • 15. 数组操作和类型检测<br />$.inArray // 可以使用Array.indexOf代替<br />$.makeArray // 很有用, 把任何东西变成数组<br />$.merge // 可惜了这个方法<br />$.type // 返回类型字符串<br />$.isArray<br />$.isEmptyObject<br />$.isFunction<br />$.isPlainObject<br />$.isWindow<br />$.isXMLDoc<br />
  • 16. AJAX和参数<br />$.param<br />$.paramSpecial中文jsonp调用代替$.param<br />$.unparam<br />$.parseJSON<br />$.parseXML<br />$.globalEval<br />$.ajax<br />$.ajaxSetup<br />以下方法调用$.ajax<br />$.get<br />$.post<br />$.getJSON<br />$.getScript<br />
  • 17. 特性检测/浏览器检测/函数包装<br />$.support<br />$.browser<br />关于浏览器检测,文档中有一句话很有价值:<br />We recommend against using this property; <br />please try to use feature detection instead<br />jQuery.browser may be moved to a plugin in a future release of jQuery.<br />$.error ——当作assert使用<br />$.noop —— 空方法<br />$.proxy ——包装一个函数,改变this作用域<br />$.when<br />$.sub<br />
  • 18. 虽然在api文档中有,但不常用的方法,<br />一般应用于jQuery内部,被相应的实例方法调用<br />$.fx<br />$.data<br />$.hasData<br />$.removeData<br />$.contains <br />$.queue<br />$.dequeue<br />$.cssHooks<br />
  • 19. fdev-v4提供的静态方法<br />$.add<br />$.use<br />$.namespace<br />$.extendIf<br />$.unparam<br />$.paramSpecial<br />$.util.cookie<br />$.util.subCookie<br />$.util.substitute<br />
  • 20. 万能构造器<br />jQuery对象是如何构造的<br />jQuery对象是数组吗?<br />构造成本有多大<br />
  • 21. 回顾一下<br />varjQuery = function() {<br /> return new jQuery.fn.init(selector, context);<br />}<br />jQuery.fn = {<br /> init: function(selector, context) {<br /> },<br />
  • 22. 1. $(null|false|…);<br />2. $(element);<br />3. $(‘body’)<br />init: function(selector, context) (<br /> // 1. 支持空selector<br /> if (!selector) {<br /> return this;<br /> }<br /> // 2. 原生dom节点<br />if (selector.nodeType) {<br />this.context = this[0] = selector;<br />this.length = 1;<br /> return this;<br /> }<br />
  • 23. // 3. 字符串 body<br /> if (selector === 'body') {<br />this.context = document;<br /> this[0] = document.body;<br />this.selector = 'body';<br />this.length = 1;<br /> return this;<br /> }<br />现在我们知道:<br />jQuery对象是普通的Object, 不是Array, 只是包含的property为数字,所以看起来像数组<br />
  • 24. 4. $(function() {<br />console.debug(‘domready’)<br />})<br />5. $(array|collection)<br />//--------------------------------------------------------------------------------------<br /> // 4. function<br /> } else if (jQuery.isFunction(selector)) {<br /> return jQuery.ready(selector);<br /> // 等效于 $(document).ready(function()…<br /> }<br /> // 5. collection / array<br /> return jQuery.makeArray(selector, this);<br />
  • 25. 6. $('<div></div>')<br />7. $('<div>')<br />8. $('<div />')<br />selector = [ doc.createElement( ret[1] ) ];<br />9. $('<img>', {<br /> width: '100',<br /> height: '200'<br />});<br />selector = [ doc.createElement( ret[1] ) ];<br />jQuery.fn.attr.call( selector, context, true );<br />所以上述相当于 $(‘<img>’).attr(…<br />
  • 26. 10. html片段和id选择器<br />$(‘<a href=“#”>这个html很复杂</a>') <br />jQuery.buildFragment( [ match[1] ], [ doc ] ); <br />1. 如果片段小于0.5K, 可cache, 以加快创建速度<br />2. createDocumentFragment()创建节点<br />3. innerHTML或 createTextNode来创建内容<br />11. $(‘#id’) // 注意,这里需要#, 因为要使用CSS3选 择器<br />elem = document.getElementById( match[2] );<br />
  • 27. 12. css3选择器<br />$('div.myclass', [context]) ---> $(context).find('div.myclass') <br /> ----> $(context). pushStack(… 这一步会构造一个新的jQuery对象<br /> -----> jQuery.find === Sizzle;<br />所以采用css 3选择器的时候, 实际上会生成两个jQuery对象<br />不过不用担心,jQuery对象很小, 下面看看它的成本。<br />
  • 28. jQuery对象属性内存结构<br />看以上结构知道,jQuery对象是简单的轻量级对象,构造成本很小,<br />并且GC对小对象的回收效率非常高,所以从这上面讲不用担心效率和内存问题。<br />我在自己机子上构造了10万个jQuery对象,大概占用32M内存空间。<br />
  • 29. 深入jQuery事件模型<br />页面中有下面代码:<br /><a href="#" class="link-a">Click Me A</a><br /><a href="#" class="link-b">Click Me B</a><br /><script><br />(function($) {<br />$('a.link-a').click(function() {<br />console.debug('click a');<br />});<br />$('a.link-a').click(function() {<br />console.debug('click a2');<br />});<br />$('a.link-a').dblclick(function() {<br />console.debug('dbclick');<br />});<br />$('a.link-b').click(function() {<br />console.debug('click other');<br />});<br />})(jQuery);<br /></script><br />
  • 30. 在firebug的脚本监控中输入jQuery.cache<br />再查看节点的DOM<br />
  • 31. 在源码中有这样一个字段:1328行<br />jQuery.extend({ <br />expando: "jQuery" +<br /> ( jQuery.fn.jquery + Math.random() ).replace( /D/g, "" ),<br />
  • 32. 一个节点一个事件一个handler<br />2197行:<br />elemData.handle = eventHandle = function() { <br /> return jQuery.event.handle.apply( eventHandle.elem, arguments ) :<br />};<br />2250行<br />if ( elem.addEventListener ) {<br />elem.addEventListener( type, eventHandle, false ); <br />} else if ( elem.attachEvent ) {<br />elem.attachEvent( “on” + type, eventHandle );<br />}<br />那么jQuery.event.handle应该是真正调用用户操作的地方<br />
  • 33. 将上图数据结构展开<br />有了上图基础,看jQuery事件代码就容易多了,jQuery的事件也就不再神秘<br />
  • 34. 事件冒泡 live & delegate<br />问题:<br />有何区别<br />如果实现<br />其实是一个问题: 事件最终挂接到哪里?<br />
  • 35. 还是源码<br />delegate: function( selector, types, fn) {<br /> return this.live( types, fn, selector); <----- 第三个参数jq内部使用<br />}<br />
  • 36. jQuery.fn.live = function(types, fn, selector) {<br />var context = selector ? this : $(this.context);<br /> …<br />for ( var j = 0, l = context.length; j < l; j++ )<br />jQuery.event.add( context[j], "live." + liveConvert( type, <br />}<br />总结:<br />1. live 事件挂接在 jQuery对象的context上(这里的context不是jQuery的第二个参数)一般为document<br />2. delegate事件挂接在当前jQuery对象包含的节点上<br />简单地说:<br />live挂接在document上(适合不复杂的冒泡)<br />delegate挂接在指定节点上 (比较精细)<br />
  • 37. 谢谢<br />谁教我做PPT啊!<br />

×