十四个有用的jquery技巧

1. Methods Return the jQuery Object 

jquery大多数方法返回的都是jquery对象,这非常的有用,而且jquery允许链式调用

1 $someDiv.attr('class', 'someClass').hide().html('new stuff');

因为返回的总是jquery对象,所以我们有时可以移除不必要的代码。比如,考虑下面的代码:

1 var someDiv = $('#someDiv');
2 someDiv.hide();

上边的代码非常的好,但是你可以很容易的把两句合成一句,而得到相同的结果。如下所示:

1 var someDiv = $('#someDiv').hide();

通过这种方法我们同样可以隐藏someDiv元素,返回的是someDiv变量的引用

2. The Find Selector

jQuery有非常强大的Sizzle引擎来实现选择器,只要你写的选择器不是很差,jQuery都会做出优化,你一般不必担心太多。然而,我们可以稍微做一些改进,这可以使你的脚本性能略有提高。

一般在jquery中能不要用Sizzle引擎就不要用,当然只要有可能,就尽量使用.find()方法。当然有些时候这是不可能的。

1 // Fine in modern browsers, though Sizzle does begin "running"
2  $('#someDiv p.someClass').hide();
3
4  // Better for all browsers, and Sizzle never inits.
5  $('#someDiv').find('p.someClass').hide();

上面两行代码执行的结果是完全一样的,但是下面一句的效率要比上面一句的执行效率高。

现代浏览器(除IE6,IE7)都有QuerySelectorAll支持,能允许你像CSS选择器一样获取对象,而不需要用到jQuery中的Sizzle引擎。jQuery会在使用自己的引擎之前检查是否存在这个函数。

对于IE6/IE7,就需要jQuery使用Sizzle引擎,jQuery会把你的选择器转化成一个数组,并且通过从右往左来迭代匹配。通过正则表达式匹配页面每一个元素,所以你的可以尽量减少选择器的层级,尽可能的使用最右边的选择器,比如使用ID选择器等;这个规则和我们的css的查找规则是一致的,如果你要优化css选择器也要知道这个规则:从右往左来迭代匹配!

尺度把握:

1.保持代码简单

2.尽可能的使用find()查找,使用浏览器的原生查找函数

3.尽可能使用最右边的选择器,比如ID等

Context Instead?

我们还可以给你的选择器添加一个选择环境(限制范围)。例如:

1 $('.someElements', '#someContainer').hide();

这段代码用来获取#someContainer对象下的所有someElements类对象。这种方法可以有效地限制DOM遍历的范围,可是在jquery的实现机制用用的是find()方法。

1 $('#someContainer')
2 .find('.someElements')
3 .hide();
证明:
1 // HANDLE: $(expr, context)
2 // (which is just equivalent to: $(context).find(expr)
3 } else {
4 return jQuery( context ).find( selector );
5 }

3. Don’t Abuse $(this)

如果我们不知道DOM各种各样的属性和方法,就会滥用jquery对象

1 $('#someAnchor').click(function() {
2 alert( $(this).attr('id') );
3 });
1 $('#someAnchor').click(function() {
2 alert( this.id );
3 });

上边两段代码,下边的方法性能会更好。

请注意,下面的三个属性应该是经常通过jquery访问的,"src","href"和"style"。这些属性在旧版本的IE浏览器当中需要使用getAttribute方法来实现。

证明:

1 // jQuery Source
2  var rspecialurl = /href|src|style/;
3  // ...
4  var special = rspecialurl.test( name );
5  // ...
6  var attr = !jQuery.support.hrefNormalized && notxml && special ?
7 // Some attributes require a special call on IE
8   elem.getAttribute( name, 2 ) :
9 elem.getAttribute( name );  

更糟糕的是反复的查询DOM和创建jquery对象。例如:

1 $('#elem').hide();
2 $('#elem').html('bla');
3 $('#elem').otherStuff();

希望你知道这段代码的效率是多么的低和改进它的方法,如果不知道,没有关系,我们这里可以使用jquery链或者缓存#elem对象。

1 // This works better
2  $('#elem').hide().html('bla').otherStuff();
3
4  // Or this, if you prefer for some reason.
5  var elem = $('#elem');
6 elem.hide();
7 elem.html('bla');
8 elem.otherStuff();

4. jQuery’s Shorthand Ready Method

对jquery来说,监听document是否加载完毕非常容易。

1 $(document).ready(function() {
2 // let's get up in heeya
3  });

Though, it’s very possible that you might have come across a different, more confusing wrapping function.

1 $(function() {
2 // let's get up in heeya
3 });

虽然后者的可读性不如前者,但是却是完全相同的。可以查看一下jquery的源代码

// HANDLE: $(function)
// Shortcut for document ready
if ( jQuery.isFunction( selector ) ) {
	return rootjQuery.ready( selector );
}

rootjQuery is simply a reference to the root jQuery(document). When you pass a selector to the jQuery function, it’ll determine what type of selector you passed: string, tag, id, function, etc. If a function was passed, jQuery will then call its ready() method, and pass your anonymous function as the selector.

5. Keep your Code Safe

If developing code for distribution, it’s always important to compensate for any possible name clashing. What would happen if some script, imported after yours, also had a $ function? Bad stuff!

The answer is to either call jQuery’s noConflict(), or to store your code within a self-invoking anonymous function, and then pass jQuery to it.

方法一、NoConflict

1 var j = jQuery.noConflict();
2 // Now, instead of $, we use j.
3 j('#someDiv').hide();
4
5 // The line below will reference some other library's $ function.
6 $('someDiv').style.display = 'none';

Be careful with this method, and try not to use it when distributing your code. It would really confuse the user of your script!

方法二、Passing jQuery

1 (function($) {
2 // Within this function, $ will always refer to jQuery
3 })(jQuery);

The final parens at the bottom call the function automatically – function(){}(). However, when we call the function, we also pass jQuery, which is then represented by $.

方法三、Passing $ via the Ready Method

1 jQuery(document).ready(function($) {
2 // $ refers to jQuery
3 });
4 // $ is either undefined, or refers to some other library's function.

6. Be Smart

记住,jquery也仅仅是javascript,不要以为他有能力来改善你糟糕透顶的代码。意思也就是,正如我们必须优化事物的javascript声明,对jquery中的各种方法来说是一样的。我们为什么不这样做呢?它只是一个辅助的方法,在后面创建一个声明。

// 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();
});
  1. 搜索anotherDiv用来迭代循环
  2. Grabs the innerHTML property twice
  3. Creates a new jQuery object, all to access the text of the element.

改善后的代码:

var someDivs = $('#container').find('.someDivs'),
      contents = [];
someDivs.each(function() {
	contents.push( this.innerHTML );
});
$('#anotherDiv').html( contents.join(' ') );

This way, within the each (for) method, the only task we're performing is adding a new key to an array…as opposed to querying the DOM, grabbing the innerHTML property of the element twice, etc.

Document Fragments

While we're at it, another option for these sorts of situations is to use document fragments.

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 );

The key here is that there are multiple ways to accomplish simple tasks like this, and each have their own performance benefits from browser to browser. The more you stick with jQuery and learn JavaScript, you also might find that you refer to JavaScript's native properties and methods more often. And, if so, that's fantastic!

jQuery provides an amazing level of abstraction that you should take advantage of, but this doesn't mean that you're forced into using its methods. For example, in the fragment example above, we use jQuery's each method. If you prefer to use a for or while statement instead, that's okay too!

With all that said, keep in mind that the jQuery team have heavily optimized this library. The debates about jQuery's each() vs. the native for statement are silly and trivial. If you are using jQuery in your project, save time and use their helper methods. That's what they're there for! 

7. AJAX Methods

If you're just now beginning to dig into jQuery, the various AJAX methods that it makes available to us might come across as a bit daunting; though they needn't. In fact, most of them are simply helper methods, which route directly to $.ajax.

  • get
  • getJSON
  • post
  • ajax

As an example, let's review getJSON, which allows us to fetch JSON.

$.getJSON('path/to/json', function(results) {
	// callback
	// results contains the returned data object
});

Behind the scenes, this method first calls $.get

getJSON: function( url, data, callback ) {
	return jQuery.get(url, data, callback, "json");
}

$.get then compiles the passed data, and, again, calls the "master" (of sorts) $.ajax method.

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
	});
}

Finally, $.ajax performs a massive amount of work to allow us the ability to successfully make asynchronous requests across all browsers!

What this means is that you can just as well use the $.ajax method directly and exclusively for all your AJAX requests. The other methods are simply helper methods that end up doing this anyway. So, if you want, cut out the middle man. It's not a significant issue either way.

Just Dandy

$.getJSON('path/to/json', function(results) {
	// callback
	// results contains the returned data object
});

Microscopically More Efficient

$.ajax({
	type: 'GET',
	url : 'path/to/json',
	data : yourData,
	dataType : 'json',
	success : function( results ) {
		console.log('success');
	})
});

8. Accessing Native Properties and Methods

So you've learned a bit of JavaScript, and have learned that, for instance, on anchor tags, you can access attribute values directly:

var anchor = document.getElementById('someAnchor');
 //anchor.id
// anchor.href
// anchor.title
// .etc

The only problem is that this doesn't seem to work when you reference the DOM elements with jQuery, right? Well of course not.

Won't Work

// Fails
var id = $('#someAnchor').id;

So, should you need to access the href attribute (or any other native property or method for that matter), you have a handful of options. 

// 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;

The get method is particularly helpful, as it can translate your jQuery collection into an array.

9. Detect AJAX Requests with PHP

Certainly, for the huge majority of our projects, we can't only rely on JavaScript for things like validation, or AJAX requests. What happens when JavaScript is turned off? For this very reason, a common technique is to detect whether an AJAX request has been made with your server-side language of choice.

jQuery makes this ridiculously simple, by setting a header from within the $.ajax method.

// 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");
}
With this header set, we can now use PHP (or any other language) to check for this header, and proceed accordingly. For this, we check the value of $_SERVER['HTTP_X_REQUESTED_WITH'].

Wrapper

function isXhr() {
  return $_SERVER['HTTP_X_REQUESTED_WITH'] === 'XMLHttpRequest';
}

10. jQuery and $

Ever wonder why/how you can use jQuery and $ interchangeably? To find your answer, view the jQuery source, and scroll to the very bottom. There, you'll see:

window.jQuery = window.$ = jQuery;

The entire jQuery script is, of course, wrapped within a self-executing function, which allows the script to limit the number of global variables as much as possible. What this also means, though, is that the jQuery object is not available outside of the wrapping anonymous function.

To fix this, jQuery is exposed to the global window object, and, in the process, an alias - $ - is also created.

11. Conditionally Loading jQuery

HTML5 Boilerplate offers a nifty one-liner that will load a local copy of jQuery if, for some odd reason, your chosen CDN is down.

<!-- 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>

To "phrase" the code above: if window.jQuery is undefined, there must have been a problem downloading the script from the CDN. In that case, proceed to the right side of the && operator, and insert a script linking to a local version of jQuery.

12. jQuery Filters

$('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"

Note: jQuery.expr[':'] is simply an alias for jQuery.expr.filters.

13. A Single Hover Function

As of jQuery 1.4, we can now pass only a single function to the hover method. Before, both the in and out methods were required.

Before

$('#someElement').hover(function() {
  // mouseover
}, function() {
 // mouseout
});

Now

$('#someElement').hover(function() {
  // the toggle() method can be used here, if applicable
});

Note that this isn't an old vs. new deal. Many times, you'll still need to pass two functions to hover, and that's perfectly acceptable. However, if you only need to toggle some element (or something like that), passing a single anonymous function will save a handful of characters or so!

14. Passing an Attribute Object

As of jQuery 1.4, we can now pass an object as the second parameter of the jQuery function. This is helpful when we need to insert new elements into the DOM. For example:

Before

$('<a />')
  .attr({
    id : 'someId',
    className : 'someClass',
    href : 'somePath.html'
  });

After

$('</a>', {
    id : 'someId',
    className : 'someClass',
    href : 'somePath.html'
});

Not only does this save a few characters, but it also makes for cleaner code. In addition to element attributes, we can even pass jQuery specific attributes and events, like click or text.

英文原文:http://net.tutsplus.com/tutorials/javascript-ajax/14-helpful-jquery-tricks-notes-and-best-practices/

If developing code for distribution, it’s always important to compensate for any possible name clashing. What would happen if some script, imported after yours, also had a $ function? Bad stuff!

The answer is to either call jQuery’s noConflict(), or to store your code within a self-invoking anonymous function, and then pass jQuery to it.

posted @ 2010-10-06 17:27  1024114660  阅读(290)  评论(0)    收藏  举报