jQuery 中的 39 個技巧

918之初發表於2016-12-16

1.當document文件就緒時執行JavaScript程式碼。

我們為什麼使用jQuery庫呢?原因之一就在於我們可以使jQuery程式碼在各種不同的瀏覽器和存在bug的瀏覽器上完美執行。

<script src="http://code.jquery.com/jquery-1.10.2.min.js"></script>

        <script>

            // Different ways to achieve the Document Ready event

            // With jQuery
            $(document).ready(function(){ /* ... */});

            // Short jQuery
            $(function(){ /* ... */});

            // Without jQuery (doesn't work in older IE versions)
            document.addEventListener('DOMContentLoaded',function(){
                // Your code goes here
            });

            // The Trickshot (works everywhere):

            r(function(){
                alert('DOM Ready!');
            })

            function r(f){/in/.test(document.readyState)?setTimeout('r('+f+')',9):f()}

        </script>

2.使用route。

<script src="http://code.jquery.com/jquery-1.10.2.min.js"></script>

        <script>

            var route = {
                _routes : {},    // The routes will be stored here

                add    : function(url, action){
                    this._routes[url] = action;
                },

                run : function(){
                    jQuery.each(this._routes, function(pattern){
                        if(location.href.match(pattern)){
                            // "this" points to the function to be executed
                            this();
                        }
                    });
                }
            }

            // Will execute only on this page:
            route.add('002.html', function(){
                alert('Hello there!')
            });

            route.add('products.html', function(){
                alert("this won't be executed : (")
            });

            // You can even use regex-es:
            route.add('.*.html', function(){
                alert('This is using a regex!')
            });

            route.run();

        </script>

3.使用JavaScript中的AND技巧。

使用&&操作符的特點是如果操作符左邊的表示式是false,那麼它就不會再判斷操作符右邊的表示式了。所以:

// Instead of writing this:
if($('#elem').length){
    // do something
}

// You can write this:

$('#elem').length && log("doing something");

4. is()方法比你想象的更為強大。

下面舉幾個例子,我們先寫一個id為elem的div。js程式碼如下:

// First, cache the element into a variable:
var elem = $('#elem');

// Is this a div?
elem.is('div') && log("it's a div");

// Does it have the bigbox class?
elem.is('.bigbox') && log("it has the bigbox class!");

// Is it visible? (we are hiding it in this example)
elem.is(':not(:visible)') && log("it is hidden!");

// Animating
elem.animate({'width':200},1);

// is it animated?
elem.is(':animated') && log("it is animated!");

其中判斷是否為動畫我覺得非常不錯。

5.判斷你的網頁一共有多少元素。

通過使用$(“*”).length();方法可以判斷網頁的元素數量。

// How many elements does your page have?
log('This page has ' + $('*').length + ' elements!');

6.使用length()屬性很笨重,下面我們使用exist()方法。

/ Old way
log($('#elem').length == 1 ? "exists!" : "doesn't exist!");

// Trickshot:

jQuery.fn.exists = function(){ return this.length > 0; }

log($('#elem').exists() ? "exists!" : "doesn't exist!");

7.jQuery方法$()實際上是擁有兩個引數的,你知道第二個引數的作用嗎?

// Select an element. The second argument is context to limit the search
// You can use a selector, jQuery object or dom element

$('li','#firstList').each(function(){
    log($(this).html());
});

log('-----');

// Create an element. The second argument is an
// object with jQuery methods to be called

var div = $('<div>',{
    "class": "bigBlue",
    "css": {
        "background-color":"purple"
    },
    "width" : 20,
    "height": 20,
    "animate" : {   // You can use any jQuery method as a property!
        "width": 200,
        "height":50
    }
});

div.appendTo('#result');

8.使用jQuery我們可以判斷一個連結是否是外部的,並來新增一個icon在非外部連結中,且確定開啟方式。

這裡用到了hostname屬性。

<ul id="links"> 
   <li><a href="007.html">The previous tip</a></li> 
   <li><a href="./009.html">The next tip</a></li>
   <li><a href="http://www.google.com/">Google</a></li> 
</ul>

// Loop through all the links
$('#links a').each(function(){

    if(this.hostname != location.hostname){
        // The link is external
        $(this).append('<img src="assets/img/external.png" />')
               .attr('target','_blank');
    }

});

9.jQuery中的end()方法可以使你的jQuery鏈更加高效。

<ul id="meals"> <li> <ul class="breakfast"> <li class="eggs">No</li> <li class="toast">No</li> <li class="juice">No</li> </ul> </li> </ul>
// Here is how it is used:

var breakfast = $('#meals .breakfast');

breakfast.find('.eggs').text('Yes')
                      .end() // back to breakfast
                      .find('.toast').text('Yes')
                      .end()
                      .find('.juice').toggleClass('juice coffee').text('Yes');

breakfast.find('li').each(function(){
    log(this.className + ': ' + this.textContent)
});

10.也許你希望你的web 應用感覺更像原生的,那麼你可以阻止contextmenu預設事件。

        <script>
            // Prevent right clicking on this page
            $(function(){
                $(document).on("contextmenu",function(e){
                    e.preventDefault();
                });
            });
        </script>

11.一些站點可能會使你的網頁在一個bar下面,即我們所看到在下面的網頁是iframe標籤中的,我們可以這樣解決。

// Here is how it is used:

if(window != window.top){
    window.top.location = window.location;
}
else{
    alert('This page is not displayed in a frame. Open 011.html to see it in action.');
}

12.你的內聯樣式表並不是被設定為不可改變的,如下:

// Make the stylesheet visible and editable
$('#regular-style-block').css({'display':'block', 'white-space':'pre'})
                         .attr('contentEditable',true);

這樣即可改變內聯樣式了。

13.有時候我們不希望網頁的某一部分內容被選擇比如複製貼上這種事情,我們可以這麼做:

<p class="descr">In certain situations you might want to prevent text on the page from being selectable. Try selecting this text and hit view source to see how it is done.</p>

     <script>
            // Prevent text from being selected
            $(function(){
                $('p.descr').attr('unselectable', 'on')
                           .css('user-select', 'none')
                           .on('selectstart', false);
          });
     </script>

這樣,內容就不能被選擇啦。

14.從CDN中引入jQuery,這樣的方法可以提高我們網站的效能,並且引入最新的版本也是一個不錯的主意。

下面會介紹四種不同的方法。

        <!-- Case 1 - requesting jQuery from the official CDN -->
        <script src="http://code.jquery.com/jquery-1.10.2.min.js"></script>

        <!-- Case 2 - requesting jQuery from Google's CDN (notice the protocol) -->
        <!-- <script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script> -->

        <!-- Case 3 - requesting the latest minor 1.8.x version (only cached for an hour) -->
        <!-- <script src="//ajax.googleapis.com/ajax/libs/jquery/1.10/jquery.min.js"></script> -->

        <!-- Case 4 - requesting the absolute latest jQuery version (use with caution) -->
        <!-- <script src="http://code.jquery.com/jquery.min.js"></script> -->

15.保證最小的DOM操作。

我們知道js操作DOM是非常浪費資源的,我們可以看看下面的例子。

CODE
// Bad
//var elem = $('#elem');
//for(var i = 0; i < 100; i++){
//    elem.append('<li>element '+i+'</li>');
//}

// Good
var elem = $('#elem'),
    arr = [];

for(var i = 0; i < 100; i++){
    arr.push('<li>element '+i+'</li>');
}

elem.append(arr.join(''));

16.更方便的分解URL。

也許你會使用正規表示式來解析URL,但這絕對不是一種好的方法,我們可以借用a標籤來實現它。

// You want to parse this address into parts:
var url = 'http://tutorialzine.com/books/jquery-trickshots?trick=12#comments';

// The trickshot:
var a = $('<a>',{ href: url });

log('Host name: ' + a.prop('hostname'));
log('Path: ' + a.prop('pathname'));
log('Query: ' + a.prop('search'));
log('Protocol: ' + a.prop('protocol'));
log('Hash: ' + a.prop('hash'));

17.不要害怕使用vanilla.js。

jQuery揹負的太多,這便是原因,你可以用一般的js。

// Print the IDs of all LI items
$('#colors li').each(function(){

    // Access the ID directly, instead
    // of using jQuery's $(this).attr('id')

    log(this.id);

});

18.最優化你的選擇器

// Let's try some benchmarks!

var iterations = 10000, i;

timer('Fancy');

for(i=0; i < iterations; i++){
    // This falls back to a SLOW JavaScript dom traversal
    $('#peanutButter div:first');
}

timer_result('Fancy');

timer('Parent-child');

for(i=0; i < iterations; i++){
    // Better, but still slow
    $('#peanutButter div');
}

timer_result('Parent-child');

timer('Parent-child by class');

for(i=0; i < iterations; i++){
    // Some browsers are a bit faster on this one
    $('#peanutButter .jellyTime')

19.快取你的selector。

// Bad:
// $('#pancakes li').eq(0).remove();
// $('#pancakes li').eq(1).remove();
// $('#pancakes li').eq(2).remove();

// Good:
var pancakes = $('#pancakes li');

pancakes.eq(0).remove();
pancakes.eq(1).remove();
pancakes.eq(2).remove();

// Alternatively:
// pancakes.eq(0).remove().end()
//           .eq(1).remove().end()
//           .eq(2).remove().end();

20.對於重複的函式只定義一次

如果你追求程式碼的更高效能,那麼當你設定事件監聽程式時必須小心,只定義一次函式然後把它的名字作為事件處理程式傳遞是不錯的方法。

$(document).ready(function(){
    function showMenu(){
        alert('Showing menu!');
        // Doing something complex here
    }

    $('#menuButton').click(showMenu);
    $('#menuLink').click(showMenu);

});

21.像對待陣列一樣地對待jQuery物件

由於jQuery物件有index值和長度,所以這意味著我們可以把物件當作普通的陣列對待。這樣也會有更好地效能。

var arr = $('li'),
    iterations = 100000;

timer('Native Loop');

for(var z=0;z<iterations;z++){

    var length = arr.length;
    for(var i=0; i < length; i++){
      arr[i];
    }
}
timer_result('Native Loop');

timer('jQuery Each');

for(z=0;z<iterations;z++){

    arr.each(function(i, val) {
      this;
    });
}
timer_result('jQuery Each');

22.當做複雜的修改時要分離元素。

修改一個dom元素要求網頁重繪,這個代價是高昂的,所以如果你想要再提高效能,就可以嘗試著當對一個元素進行大量修改時先從頁面中分離這個元素,修改完之後再新增到頁面。

// Modifying in place
var elem = $('#elem');

timer('In place');

for(i=0; i &lt; iterations; i++){

    elem.width(Math.round(100*Math.random()));
    elem.height(Math.round(100*Math.random()));

}

timer_result('In place');

var parent = elem.parent();

// Detaching first
timer('Detached');

elem.detach();

for(i=0; i &lt; iterations; i++){

    elem.width(Math.round(100*Math.random()));
    elem.height(Math.round(100*Math.random()));

}

elem.appendTo(parent);

timer_result('Detached');

23.不要一直等待load事件。

我們已經習慣了把我們所有的程式碼都放在ready的事件處理程式中,但是,如果你的html頁面很龐大,decument ready恐怕會被延遲了,所以對於一些我們不希望ready後才可以觸發的事件可以放在html的head元素中。

<script>

            // jQuery is loaded at this point. We can use
            // event delegation right away to bind events
            // even before $(document).ready:

            $(document).on('click', '#clickMe', function(){
                alert('Hit view source and see how this is made');
            });

            $(document).ready(function(){

                // This is where you would usually bind event handlers,
                // but as we are using delegation, there is no need to.

                // $('#clickMe').click(function(){ alert('Hey!'); });
            });

            // Note: You should place your script tags at the bottom of the page.
            // I have included them in the head only to demonstrate that we can bind
            // events before document ready and before the elements are created.

        </script>

24.當使用js給多個元素新增樣式時更好的做法是建立一個style元素。

我們之前提到過,操作dom是非常慢的,所以當新增多個元素的樣式時建立一個style元素並新增到document中是更好的做法。

<ul id="testList">
 <li>Item</li> <li>Item</li> <li>Item</li> <li>Item</li> <li>Item</li> <li>Item</li> <li>Item</li> <li>Item</li> <li>Item</li> <li>Item</li> <li>Item</li> <li>Item</li> <li>Item</li> <li>Item</li> <li>Item</li> <li>Item</li> <li>Item</li>
 </ul>

var style = $('<style>');

// Try commenting out this line, or change the color:
style.text('#testList li{ color:red;}');

// Placing it before the result section so it affects the elements
style.prependTo('#result');

25.給html元素分配一個名為JS的class。

現代的web apps非常的依賴js,這裡的一個技巧就是隻有當js可用時才能顯示特定的元素。看下面的程式碼。

$(document).ready(function(){
    $('html').addClass('JS');
});

  html.JS #message { display:block; }
 #message {display:none;}

這樣,只有js可用的時候id為message的元素才會顯示;如果不支援js,則該元素不會顯示。

26.監聽不存在的元素上的事件。

jQuery擁有一個先進的事件處理機制,通過on()方法可以監聽還不存在的事件。 這是因為on方法可以傳遞一個元素的子元素選擇器作為引數。看下面的例子:

<ul id="testList"> <li>Old</li> <li>Old</li> <li>Old</li> <li>Old</li> </ul>

var list = $('#testList');

// Binding an event on the list, but listening for events on the li items:
list.on('click','li',function(){
    $(this).remove();
});

// This allows us to create li elements at a later time,
// while keeping the functionality in the event listener

list.append('<li>New item (click me!)</li>');

這樣,即使li是後建立的,也可以通過on()方法來監聽。

27.只使用一次事件監聽。

有時,我們只需要繫結只執行一次的事件處理程式。那麼one()方法是一個不錯的選擇,通過它你就可以高枕無憂了。

<button id="press">Press me!</ul>
var press = $('#press');

// There is a method that does exactly that, the one():
press.one('click',function(){
    alert('This alert will pop up only once');
});

// What this method does, is call on() behind the scenes,
// with a 1 as the last argument:
// press.on('click',null,null,function(){alert('I am the one and only!');}, 1);

28.模擬觸發事件。

我們可以通過使用trigger模擬觸發一個click事件。

<button id="press">Press me!</ul>
var press = $('#press');

// Just a regular event listener:
press.on('click',function(e, how){
    how = how || '';
    alert('The buton was clicked ' + how + '!');
});

// Trigger the click event
press.trigger('click');

// Trigger it with an argument
press.trigger('click',['fast']);

29.使用觸控事件。

使用觸控事件和相關的滑鼠事件並沒有太多不同,但是你得有一個方便的移動裝置來測試會更好。看下面這個例子。

// Define some variables
var ball = $('&lt;div id="ball"&gt;&lt;/div&gt;').appendTo('body'),
startPosition = {}, elementPosition = {};

// Listen for mouse and touch events
ball.on('mousedown touchstart',function(e){
    e.preventDefault();

    // Normalizing the touch event object
    e = (e.originalEvent.touches) ? e.originalEvent.touches[0] : e;

    // Recording current positions
    startPosition = {x: e.pageX, y: e.pageY};
    elementPosition = {x: ball.offset().left, y: ball.offset().top};

    // These event listeners will be removed later
    ball.on('mousemove.rem touchmove.rem',function(e){
        e = (e.originalEvent.touches) ? e.originalEvent.touches[0] : e;

        ball.css({
            top:elementPosition.y + (e.pageY - startPosition.y),
            left: elementPosition.x + (e.pageX - startPosition.x),
        });

    });
});

ball.on('mouseup touchend',function(){
    // Removing the heavy *move listeners
    ball.off('.rem');
});

30.更好地使用on()/off()方法。

在jQuery1.7版本時對事件處理進行了簡化,看看下面的例子吧。

<div id="holder"> <button id="button1">1</button> <button id="button2">2</button> <button id="button3">3</button> <button id="button4">4</button> <button id="clear" style="float: right;">Clear</button> </div>

// Lets cache some selectors

var button1 = $('#button1'),
    button2 = $('#button2'),
    button3 = $('#button3'),
    button4 = $('#button4'),
    clear = $('#clear'),
    holder = $('#holder');

// Case 1: Direct event handling
button1.on('click',function(){
    log('Click');
});

// Case 2: Direct event handling of multiple events
button2.on('mouseenter mouseleave',function(){
    log('In/Out');
});

// Case 3: Data passing
button3.on('click', Math.round(Math.random()*20), function(e){

    // This will print the same number over and over again,
    // as the random number above is generated only once:
    log('Random number: ' + e.data);

});

// Case 4: Events with a namespace
button4.on('click.temp', function(e){
    log('Temp event!');
});

button2.on('click.temp', function(e){
    log('Temp event!');
});

// Case 5: Using event delegation
$('#holder').on('click', '#clear', function(){
    log.clear();
});

// Case 6: Passing an event map
var t; // timer

clear.on({

    'mousedown':function(){

        t = new Date();

    },

    'mouseup':function(){

        if(new Date() - t &gt; 1000){

            // The button has been held pressed
            // for more than a second. Turn off
            // the temp events

            $('button').off('.temp');
            alert('The .temp events were cleared!');
        }

    }
});

31.更快地阻止預設事件行為。

我們知道js中可以使用preventDefault()方法來阻止預設行為,但是jQuery對此提供了更簡單的方法。如下:

<a href="http://google.com/" id="goToGoogle">Go To Google</a>

$('#goToGoogle').click(false);

32.使用event.result連結多個事件處理程式。

對一個元素繫結多個事件處理程式並不常見,而使用event.result更可以將多個事件處理程式聯絡起來。看下面的例子。

<button id="press">點選</button>
 <script src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
 <script>

var press = $('#press');
press.on('click',function(){
    return 'Hip';
});

// The second event listener has access
// to what was returned from the first

press.on('click',function(e){
    console.log(e.result + ' Hop!');
});
 </script>

這樣,控制檯會輸出Hip Hop!

33.建立你自己習慣的事件。

你可以使用on()方法建立自己喜歡的事件名稱,然後通過trigger來觸發。舉例如下:

<button id="button1">Jump</button> <button id="button2">Punch</button> <button id="button3">Click</button> <button id="clear" style="float: right;">Clear</button> <div id="eventDiv"></div>
     <script src="http://code.jquery.com/jquery-1.10.2.min.js"></script>

     <script>

var button1 = $('#button1'),
    button2 = $('#button2'),
    button3 = $('#button3'),
    clear = $('#clear'),
    div = $('#eventDiv');

div.on({
    jump : function(){
        alert('Jumped!');
    },

    punch : function(e,data){
        alert('Punched '+data+'!');
    },

    click : function(){
        alert('Simulated click!');
    }

});

button1.click(function(){
    div.trigger('jump');
});

button2.click(function(){
    // Pass data along with the event
    div.trigger('punch',['hard']);
});

button3.click(function(){
    div.trigger('click');
});

clear.click(function(){
    //some clear code
});

     </script>

34.在下載檔案旁顯示檔案大小。

你知道如何在不下載一個檔案的情況下通過傳送一個ajax請求頭得到一個檔案的大小嗎? 使用jQuery就很容易。

<a href="001.html" class="fetchSize">First Trickshot</a> <br /> 
<a href="034.html" class="fetchSize">This Trickshot</a> <br /> 
<a href="assets/img/ball.png" class="fetchSize">Ball.png</a> <br />

// Loop all .fetchSize links
$('a.fetchSize').each(function(){

    // Issue an AJAX HEAD request for each one
    var link = this;

    $.ajax({
        type        : 'HEAD',
        url            : link.href,
        complete    : function(xhr){

            // Append the filesize to each
            $(link).append(' (' + humanize(xhr.getResponseHeader('Content-Length')) + ')');

        }
    });

});

function humanize(size){
    var units = ['bytes','KB','MB','GB','TB','PB'];

    var ord = Math.floor( Math.log(size) / Math.log(1024) );
    ord = Math.min( Math.max(0,ord), units.length-1);

    var s = Math.round((size / Math.pow(1024,ord))*100)/100;
    return s + ' ' + units[ord];
}

注意:這個例子如何我們直接使用瀏覽器是沒法得到的,必須使用本地的web伺服器開啟執行才可以。

35.使用延遲簡化你的Ajax請求

延遲(deferreds)是一個強大的工具。jQuery對於每一個Ajax請求都會返回一個deferred物件。 deferred.done()方法接受一個或多個引數,所有這些都引數可以是一個單一的函式或一個函式陣列。當Deferred(延遲)解決時,doneCallbacks被呼叫。回撥是依照他們新增的順序執行。一旦deferred.done()返回Deferred(延遲)物件,Deferred(延遲)可以連結其它的延遲物件,包括增加額外的.done()方法。下面這樣就會使你的程式碼更易讀:

// This is equivalent to passing a callback as the
// second argument (executed on success):

$.get('assets/misc/1.json').done(function(r){
    log(r.message);
});

// Requesting a file that does not exist. This will trigger
// the failure response. To handle it, you would normally have to
// use the full $.ajax method and pass it as a failure callback,
// but with deferreds you can can simply use the fail method:

$.get('assets/misc/non-existing.json').fail(function(r){
    log('Oops! The second ajax request was "' + r.statusText + '" (error ' + r.status + ')!');
});

36.平行的執行多個Ajax請求。

當我們需要傳送多個Ajax請求是,相反於等待一個傳送結束再傳送下一個,我們可以平行地傳送來加速Ajax請求傳送。

// The trick is in the $.when() function:

$.when($.get('assets/misc/1.json'), $.get('assets/misc/2.json')).then(function(r1, r2){
    log(r1[0].message + " " + r2[0].message);
});

37.通過jQuery獲得ip

我們不僅可以在電腦上ping到一個網站的ip,也可以通過jQuery得到。

$.get('http://jsonip.com/', function(r){ log(r.ip); });

// For older browsers, which don't support CORS
// $.getJSON('http://jsonip.com/?callback=?', function(r){ log(r.ip); });

38.使用最簡單的ajax請求

jQuery(使用ajax)提供了一個速記的方法來快速下載內容並新增在一個元素中。

<p class="content"></p> <p class="content"></p>

var contentDivs = $('.content');

// Fetch the contents of a text file:
contentDivs.eq(0).load('1.txt');

// Fetch the contents of a HTML file, and display a specific element:
contentDivs.eq(1).load('1.html #header');

39.序列化物件

jQuery提供了一個方法序列化表單值和一般的物件成為URL編碼文字字串。這樣,我們就可以把序列化的值傳給ajax()作為url的引數,輕鬆使用ajax()提交表單了。

<form action="">
First name: <input type="text" name="FirstName" value="Bill" /><br />
Last name: <input type="text" name="LastName" value="Gates" /><br />
</form>

// Turn all form fields into a URL friendly key/value string.
// This can be passed as argument of AJAX requests, or URLs.

$(document).ready(function(){
    console.log($("form").serialize()); // FirstName=Bill&LastName=Gates
});

// You can also encode your own objects with the $.param method:
log($.param({'pet':'cat', 'name':'snowbell'}));

持續更新中…

相關文章