Jika terdapat satu perkara buruk tentang jQuery, ia adalah tahap yang sangat rendah untuk bermula sehingga ia cenderung menarik orang yang tidak tahu apa-apa tentang JavaScript. Sekarang, di satu pihak, ini hebat. Walau bagaimanapun, sebaliknya, ia juga boleh membawa kepada beberapa, terus terang, kod buruk yang menjijikkan (sesetengahnya saya tulis sendiri!).
Tetapi itu tidak mengapa; pengekodan sangat teruk sehingga membuatkan nenek anda tercungap-cungap adalah satu upacara. Kuncinya adalah untuk melepasi gunung, dan itulah yang akan kita bincangkan dalam tutorial hari ini.
Adalah penting untuk diingat bahawa kebanyakan kaedah mengembalikan objek jQuery. Ini sangat berguna dan membolehkan untuk memautkan fungsi yang kerap kami gunakan.
$someDiv .attr('class', 'someClass') .hide() .html('new stuff');
Mengetahui bahawa objek jQuery sentiasa dikembalikan, kadangkala kita boleh menggunakan ini untuk mengalih keluar kod berlebihan. Sebagai contoh, pertimbangkan kod berikut:
var someDiv = $('#someDiv'); someDiv.hide();
Sebab kami "mencagar" kedudukan elemen
someDiv
adalah untuk mengehadkan bilangan kali kami perlu melintasi DOM elemen itu kepada sekali sahaja.someDiv
元素的位置,是为了将我们必须遍历该元素的 DOM 的次数限制为一次。
上面的代码完全没问题;但是,您可以轻松地将两条线合并为一条线,同时获得相同的结果。
var someDiv = $('#someDiv').hide();
这样,我们仍然隐藏 someDiv
元素,但正如我们所知,该方法也返回 jQuery 对象——然后通过 someDiv
变量引用该对象。
只要你的选择器不是糟糕得离谱,jQuery 就会尽可能地优化它们,而且你通常不需要太担心它们。不过,话虽如此,您可以进行一些改进,从而稍微提高脚本的性能。
一种这样的解决方案是在可能的情况下使用 find()
方法。如果没有必要的话,关键是不要强迫 jQuery 使用它的 Sizzle 引擎。当然,有时这是不可能的——但这没关系;但是,如果您不需要额外的开销,就不要寻找它。
// Fine in modern browsers, though Sizzle does begin "running" $('#someDiv p.someClass').hide(); // Better for all browsers, and Sizzle never inits. $('#someDiv').find('p.someClass').hide();
最新的现代浏览器支持
QuerySelectorAll
,它允许您传递类似 CSS 的选择器,而不需要 jQuery。 jQuery 本身也会检查此函数。
但是,较旧的浏览器(即 IE6/IE7)不提供支持,这是可以理解的。这意味着这些更复杂的选择器会触发 jQuery 的完整 Sizzle 引擎,该引擎虽然很出色,但确实会带来更多的开销。
Sizzle 是一大堆我可能永远无法理解的精彩代码。然而,在一句话中,它首先将您的选择器变成一个由选择器的每个组件组成的“数组”。
// Rough idea of how it works ['#someDiv, 'p'];
然后,从右到左,开始使用正则表达式破译每个项目。这也意味着选择器的最右侧部分应尽可能具体 - 例如,id
或标记名称。
底线,如果可能的话:
find()
方法。这样,我们就可以继续使用浏览器的原生功能,而不是使用 Sizzle。 还可以向选择器添加上下文,例如:
$('.someElements', '#someContainer').hide();
此代码指示 jQuery 在 jQuery 中使用 someElements
类(它们是 someContainer
的子级)包装所有元素的集合。使用上下文是限制 DOM 遍历的一种有用方法,但在幕后,jQuery 使用 find
方法来代替。
$('#someContainer') .find('.someElements') .hide();
// HANDLE: $(expr, context) // (which is just equivalent to: $(context).find(expr) } else { return jQuery( context ).find( selector ); }
$(this)
在不了解各种 DOM 属性和功能的情况下,很容易不必要地滥用 jQuery 对象。例如:
$('#someAnchor').click(function() { // Bleh alert( $(this).attr('id') ); });
如果我们对 jQuery 对象的唯一需要是访问锚标记的 id
属性,那么这是浪费的。最好坚持使用“原始”JavaScript。
$('#someAnchor').click(function() { alert( this.id ); });
请注意,应该始终通过 jQuery 访问三个属性:“src”、“href”和“style”。这些属性需要在旧版本的 IE 中使用
getAttribute
。
// jQuery Source var rspecialurl = /href|src|style/; // ... var special = rspecialurl.test( name ); // ... var attr = !jQuery.support.hrefNormalized && notxml && special ? // Some attributes require a special call on IE elem.getAttribute( name, 2 ) : elem.getAttribute( name );
更糟糕的是重复查询 DOM 和创建多个 jQuery 对象的过程。
$('#elem').hide(); $('#elem').html('bla'); $('#elem').otherStuff();
希望您已经意识到这段代码的效率有多低。如果没有,也没关系;我们都在学习。答案是要么实现链接,要么“缓存” #elem
的位置。
// This works better $('#elem') .hide() .html('bla') .otherStuff(); // Or this, if you prefer for some reason. var elem = $('#elem'); elem.hide(); elem.html('bla'); elem.otherStuff();
Ready
$(document).ready(function() { // let's get up in heeya });
someDiv
, tetapi seperti yang kita tahu, kaedah ini juga mengembalikan objek jQuery - yang kemudiannya dirujuk melalui pembolehubah someDiv
. 🎜 🎜2. 🎜Cari Pemilih🎜 🎜 Selagi pemilih anda tidak terlalu buruk, jQuery akan mengoptimumkannya sebanyak mungkin, dan anda biasanya tidak perlu terlalu risau tentangnya. Walau bagaimanapun, setelah berkata demikian, terdapat beberapa penambahbaikan yang boleh anda lakukan yang akan meningkatkan sedikit prestasi skrip anda. 🎜 🎜 Satu penyelesaian sedemikian ialah menggunakan kaedah
find()
jika boleh. Perkara utama ialah tidak memaksa jQuery menggunakan enjin Sizzlenya jika anda tidak perlu. Sudah tentu, kadangkala ini tidak mungkin - dan tidak mengapa, tetapi jika anda tidak memerlukan kos tambahan, jangan carinya. 🎜
$(function() { // let's get up in heeya });
QuerySelectorAll
, yang membolehkan anda melepasi pemilih seperti CSS tanpa memerlukan jQuery. jQuery sendiri juga menyemak fungsi ini. 🎜
🎜Walau bagaimanapun, pelayar lama (iaitu IE6/IE7) tidak memberikan sokongan, yang boleh difahami. Ini bermakna bahawa pemilih yang lebih kompleks ini mencetuskan enjin Sizzle penuh jQuery, yang, walaupun hebat, datang dengan lebih banyak overhed. 🎜
🎜
🎜Sizzle ialah sekumpulan kod hebat yang mungkin saya tidak faham. Walau bagaimanapun, dalam satu ayat, ia mula-mula menukar pemilih anda menjadi "tatasusunan" yang terdiri daripada setiap komponen pemilih. 🎜
// HANDLE: $(function) // Shortcut for document ready if ( jQuery.isFunction( selector ) ) { return rootjQuery.ready( selector ); }
id
atau nama teg. 🎜
🎜Ikhtisar, jika boleh: 🎜
find()
. Dengan cara ini, kami boleh terus menggunakan fungsi asli penyemak imbas dan bukannya menggunakan Sizzle. var j = jQuery.noConflict(); // Now, instead of $, we use j. j('#someDiv').hide(); // The line below will reference some other library's $ function. $('someDiv').style.display = 'none';
someElements
(yang merupakan anak kepada someContainer
). Menggunakan konteks ialah cara yang berguna untuk mengehadkan traversal DOM, tetapi di sebalik tabir, jQuery menggunakan kaedah cari
sebaliknya. 🎜
(function($) { // Within this function, $ will always refer to jQuery })(jQuery);
jQuery(document).ready(function($) { // $ refers to jQuery }); // $ is either undefined, or refers to some other library's function.
$(this)
🎜
🎜
Tanpa memahami pelbagai sifat dan keupayaan DOM, mudah untuk menyalahgunakan objek jQuery secara tidak perlu. Contohnya: 🎜
// jQuery's each method source each: function( object, callback, args ) { var name, i = 0, length = object.length, isObj = length === undefined || jQuery.isFunction(object); if ( args ) { if ( isObj ) { for ( name in object ) { if ( callback.apply( object[ name ], args ) === false ) { break; } } } else { for ( ; i < length; ) { if ( callback.apply( object[ i++ ], args ) === false ) { break; } } } // A special, fast, case for the most common use of each } else { if ( isObj ) { for ( name in object ) { if ( callback.call( object[ name ], name, object[ name ] ) === false ) { break; } } } else { for ( var value = object[0]; i < length && callback.call( value, i, value ) !== false; value = object[++i] ) {} } } return object; }
id
tag anchor, maka ini adalah membazir. Lebih baik berpegang pada JavaScript "mentah". 🎜
someDivs.each(function() { $('#anotherDiv')[0].innerHTML += $(this).text(); });
getAttribute
dalam versi lama IE. 🎜
var someDivs = $('#container').find('.someDivs'), contents = []; someDivs.each(function() { contents.push( this.innerHTML ); }); $('#anotherDiv').html( contents.join('') );
var someUls = $('#container').find('.someUls'), frag = document.createDocumentFragment(), li; someUls.each(function() { li = document.createElement('li'); li.appendChild( document.createTextNode(this.innerHTML) ); frag.appendChild(li); }); $('#anotherUl')[0].appendChild( frag );
#elem
. 🎜
$.getJSON('path/to/json', function(results) { // callback // results contains the returned data object });
Ready
jQuery🎜
🎜
Ia sangat mudah untuk menggunakan jQuery untuk mendengar apabila dokumen sedia untuk tindakan. 🎜
getJSON: function( url, data, callback ) { return jQuery.get(url, data, callback, "json"); }
$(function() { // let's get up in heeya });
尽管后者的可读性稍差,但上面的两个片段是相同的。不相信我?只需检查 jQuery 源代码即可。
// HANDLE: $(function) // Shortcut for document ready if ( jQuery.isFunction( selector ) ) { return rootjQuery.ready( selector ); }
rootjQuery
只是对根 jQuery(document)
的引用。当您将选择器传递给 jQuery 函数时,它将确定您传递的选择器类型:字符串、标记、id、函数等。如果传递了函数,jQuery 将调用其 ready()
方法,并将您的匿名函数作为选择器传递。
如果开发用于分发的代码,补偿任何可能的名称冲突始终很重要。如果在您的脚本之后导入的某些脚本也具有 $
函数,会发生什么情况?坏东西!
答案是要么调用 jQuery 的 noConflict()
,要么将代码存储在自调用匿名函数中,然后将 jQuery 传递给它。
var j = jQuery.noConflict(); // Now, instead of $, we use j. j('#someDiv').hide(); // The line below will reference some other library's $ function. $('someDiv').style.display = 'none';
请小心使用此方法,并在分发代码时尽量不要使用它。这真的会让脚本的用户感到困惑! :)
(function($) { // Within this function, $ will always refer to jQuery })(jQuery);
底部的最后一个括号自动调用该函数 - function(){}()
。然而,当我们调用该函数时,我们还传递了 jQuery,然后用 $
表示。
Ready
方法传递$ jQuery(document).ready(function($) { // $ refers to jQuery }); // $ is either undefined, or refers to some other library's function.
请记住 - jQuery 只是 JavaScript。不要假设它有能力弥补你的错误编码。 :)
这意味着,正如我们必须优化 JavaScript for
语句等内容一样,jQuery 的 each
方法也是如此。我们为什么不呢?它只是一个辅助方法,然后在幕后创建 for
语句。
// jQuery's each method source each: function( object, callback, args ) { var name, i = 0, length = object.length, isObj = length === undefined || jQuery.isFunction(object); if ( args ) { if ( isObj ) { for ( name in object ) { if ( callback.apply( object[ name ], args ) === false ) { break; } } } else { for ( ; i < length; ) { if ( callback.apply( object[ i++ ], args ) === false ) { break; } } } // A special, fast, case for the most common use of each } else { if ( isObj ) { for ( name in object ) { if ( callback.call( object[ name ], name, object[ name ] ) === false ) { break; } } } else { for ( var value = object[0]; i < length && callback.call( value, i, value ) !== false; value = object[++i] ) {} } } return object; }
someDivs.each(function() { $('#anotherDiv')[0].innerHTML += $(this).text(); });
anotherDiv
var someDivs = $('#container').find('.someDivs'), contents = []; someDivs.each(function() { contents.push( this.innerHTML ); }); $('#anotherDiv').html( contents.join('') );
这样,在 each
(for) 方法中,我们执行的唯一任务就是向数组添加一个新键...而不是查询 DOM,两次获取元素的 innerHTML
属性,等等
这篇技巧总体上更多地基于 JavaScript,而不是特定于 jQuery。 重点是要记住 jQuery 并不能弥补糟糕的编码。
当我们这样做时,针对此类情况的另一种选择是使用文档片段。
var someUls = $('#container').find('.someUls'), frag = document.createDocumentFragment(), li; someUls.each(function() { li = document.createElement('li'); li.appendChild( document.createTextNode(this.innerHTML) ); frag.appendChild(li); }); $('#anotherUl')[0].appendChild( frag );
这里的关键是,有多种方法可以完成这样的简单任务,并且每种方法在浏览器之间都有自己的性能优势。您越坚持使用 jQuery 并学习 JavaScript,您可能还会发现您更频繁地引用 JavaScript 的本机属性和方法。如果是这样,那就太棒了!
jQuery 提供了令人惊叹的抽象级别,您应该利用它,但这并不意味着您被迫使用它的方法。例如,在上面的片段示例中,我们使用 jQuery 的 each
方法。如果您更喜欢使用 for
或 while
语句,那也没关系!
尽管如此,请记住 jQuery 团队已经对该库进行了大量优化。关于 jQuery 的
each()
与本机for
语句的争论是愚蠢而琐碎的。如果您在项目中使用 jQuery,请使用它们的帮助器方法来节省时间。这就是他们存在的目的! :)
如果您现在才开始深入研究 jQuery,它为我们提供的各种 AJAX 方法可能会让人感到有点畏惧;尽管他们不需要。事实上,它们中的大多数只是简单的辅助方法,直接路由到 $.ajax
。
作为示例,让我们回顾一下 getJSON
,它允许我们获取 JSON。
$.getJSON('path/to/json', function(results) { // callback // results contains the returned data object });
在幕后,该方法首先调用 $.get
。
getJSON: function( url, data, callback ) { return jQuery.get(url, data, callback, "json"); }
$.get
然后编译传递的数据,并再次调用“master”(某种意义上的)$.ajax
方法。
get: function( url, data, callback, type ) { // shift arguments if data argument was omited if ( jQuery.isFunction( data ) ) { type = type || callback; callback = data; data = null; } return jQuery.ajax({ type: "GET", url: url, data: data, success: callback, dataType: type }); }
最后,$.ajax
执行了大量工作,使我们能够在所有浏览器上成功发出异步请求!
这意味着您也可以直接使用
$.ajax
方法来处理您的所有 AJAX 请求。其他方法只是辅助方法,无论如何最终都会执行此操作。所以,如果你愿意的话,就可以去掉中间人。无论如何,这都不是一个重要的问题。
$.getJSON('path/to/json', function(results) { // callback // results contains the returned data object });
$.ajax({ type: 'GET', url : 'path/to/json', data : yourData, dataType : 'json', success : function( results ) { console.log('success'); }) });
现在您已经学习了一些 JavaScript,并且已经了解,例如,在锚标记上,您可以直接访问属性值:
var anchor = document.getElementById('someAnchor'); //anchor.id // anchor.href // anchor.title // .etc
唯一的问题是,当您使用 jQuery 引用 DOM 元素时,这似乎不起作用,对吗?当然不是。
// Fails var id = $('#someAnchor').id;
因此,如果您需要访问 href
属性(或任何其他本机属性或方法),您有多种选择。
// OPTION 1 - Use jQuery var id = $('#someAnchor').attr('id'); // OPTION 2 - Access the DOM element var id = $('#someAnchor')[0].id; // OPTION 3 - Use jQuery's get method var id = $('#someAnchor').get(0).id; // OPTION 3b - Don't pass an index to get anchorsArray = $('.someAnchors').get(); var thirdId = anchorsArray[2].id;
get
方法特别有用,因为它可以将 jQuery 集合转换为数组。
当然,对于我们的绝大多数项目,我们不能仅仅依赖 JavaScript 来完成诸如验证或 AJAX 请求之类的事情。当 JavaScript 关闭时会发生什么?正是出于这个原因,一种常见的技术是检测 AJAX 请求是否是使用您选择的服务器端语言发出的。
jQuery 通过在 $.ajax
方法中设置标头,使这变得异常简单。
// Set header so the called script knows that it's an XMLHttpRequest // Only send the header if it's not a remote XHR if ( !remote ) { xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest"); }
设置此标头后,我们现在可以使用 PHP(或任何其他语言)检查此标头,并进行相应操作。为此,我们检查 $_SERVER['HTTP_X_REQUESTED_WITH']
的值。
function isXhr() { return $_SERVER['HTTP_X_REQUESTED_WITH'] === 'XMLHttpRequest'; }
有没有想过为什么/如何可以互换使用 jQuery
和 $
?要找到答案,请查看 jQuery 源代码,然后滚动到最底部。在那里,您会看到:
window.jQuery = window.$ = jQuery;
当然,整个 jQuery 脚本都包含在一个自执行函数中,这允许脚本尽可能地限制全局变量的数量。但这也意味着 jQuery 对象在包装匿名函数之外不可用。
为了解决这个问题,jQuery 被暴露给全局 window
对象,并且在此过程中,还会创建一个别名 - $
-。
HTML5 Boilerplate 提供了一个漂亮的单行代码,如果由于某种奇怪的原因您选择的 CDN 出现故障,它将加载 jQuery 的本地副本。
<!-- Grab Google CDN jQuery. fall back to local if necessary --> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script> <script>!window.jQuery && document.write('<script src="js/jquery-1.4.2.min.js"><\/script>')</script>
“表述”上面的代码:如果 window.jQuery 未定义,则从 CDN 下载脚本时一定出现问题。在这种情况下,请继续到 &&
运算符的右侧,并插入链接到本地版本 jQuery 的脚本。
高级会员:下载此视频(必须登录)
订阅我们的 YouTube 页面以观看所有视频教程!
<script> $('p:first').data('info', 'value'); // populates $'s data object to have something to work with $.extend( jQuery.expr[":"], { block: function(elem) { return $(elem).css("display") === "block"; }, hasData : function(elem) { return !$.isEmptyObject( $(elem).data() ); } } ); $("p:hasData").text("has data"); // grabs paras that have data attached $("p:block").text("are block level"); // grabs only paragraphs that have a display of "block" </script>
注意:
jQuery.expr[':']
只是jQuery.expr.filters
的别名。
从 jQuery 1.4 开始,我们现在只能将单个函数传递给 hover
方法。以前,in 和 out 方法都是必需的。
$('#someElement').hover(function() { // mouseover }, function() { // mouseout });
$('#someElement').hover(function() { // the toggle() method can be used here, if applicable });
请注意,这不是旧协议与新协议的比较。很多时候,您仍然需要将两个函数传递给 hover
,这是完全可以接受的。但是,如果您只需要切换某些元素(或类似的元素),则传递单个匿名函数将节省一些字符左右!
从 jQuery 1.4 开始,我们现在可以传递一个对象作为 jQuery 函数的第二个参数。当我们需要向 DOM 中插入新元素时,这非常有用。例如:
$('<a />') .attr({ id : 'someId', className : 'someClass', href : 'somePath.html' });
$('</a>', { id : 'someId', className : 'someClass', href : 'somePath.html' });
这不仅可以节省一些字符,而且还可以使代码更加简洁。除了元素属性之外,我们甚至可以传递 jQuery 特定的属性和事件,例如 click
或 text
。
Atas ialah kandungan terperinci 14 petua jQuery, peringatan dan amalan terbaik untuk meningkatkan kemahiran anda. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!