1. 程式人生 > >jQuery教程-jQuery高階 - 06

jQuery教程-jQuery高階 - 06

1.jQuery原型物件解密

jQuery裡面的大部分API都是在jQuery的原型物件上定義的。jQuery原始碼中對原型物件做了簡寫的處理。也就是說:jQuery.fn === jQuery.prototype,參考jQuery原始碼:

...
jQuery.fn = jQuery.prototype = {

// The current version of jQuery being used
jquery: version,

constructor: jQuery,

// The default length of a jQuery object is 0
length: 0,

toArray: function() {
  return slice.call( this );
},
...

1.1 each函式

jQuery的包裝物件封裝了each(callback)方法,以每一個匹配的元素作為上下文來執行一個函式。
意味著,每次執行傳遞進來的函式時,函式中的this關鍵字都指向一個不同的DOM元素(每次都是一個不同的匹配元素)。而且,在每次執行函式時,都會給函式傳遞一個表示作為執行環境的元素在匹配的元素集合中所處位置的數字值作為引數(從零開始的整型)。 返回 'false' 將停止迴圈 (就像在普通的迴圈中使用 'break')。返回 'true' 跳至下一個迴圈(就像在普通的迴圈中使用'continue')。

例項:

// 迭代兩個影象,並設定它們的 src 屬性。注意:此處 this 指代的是 DOM 物件而非 jQuery 物件。
// HTML 程式碼:
// <img/><img/>
$("img").each(function(i){
  this.src = "test" + i + ".jpg";
  // this 指向當前的變數的dom物件。 i是當前dom物件在選擇器返回陣列中的索引。
 });

1.2 獲取元素的個數

兩種方法可以獲取選擇器匹配的元素的個數。

第一種方法:$('p').size();
第二種方法:$('p').length

以上兩種方法都可以。推薦使用length屬性

1.3 其他屬性和方法

屬性/方法名 用法 介紹
selector $('p').selector 返回選擇器的字串
get() $('p').get(); 返回所有的選擇的dom物件的集合
get(index)
$('p').get(1); 返回第2個dom物件,索引從0開始
toArray() $('p').toArray(); 把jQuery集合中所有DOM元素恢復成一個數組。

上課程式碼

<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
</ul>

<script src="./lib/jquery-1.12.4.js"></script>
<script>
  // 陣列的方法forEach, ie9+ 
  var arr = ['a', 'b', 3, 4];
  // value陣列的元素, index陣列元素的索引
  arr.forEach(function(value, index) {
    console.log('index:',index, 'value',value)
  });

  //jQuery原型上提供了each
  $(function() {
    // jQuery.fn上提供了each方法,類似for迴圈遍歷。推薦使用each替代for
    // 引數:第一個引數是:索引,第二個引數是dom元素。
    $('li').each(function(index, elem) {
      console.log(index, elem);
    });

    // jQuery原型:獲取元素個數。
    console.log('size:', $('li').size())
    console.log('length:', $('li').length)
    console.log($('li').get());
  });
</script>

2.jQuery建構函式解密

2.1 建構函式的each方法

  • 語法:jQuery.each(object, [callback])

  • 概述

    通用例遍方法,可用於例遍物件和陣列。不同於例遍 jQuery 物件的 $().each() 方法,此方法可用於例遍任何物件。回撥函式擁有兩個引數:第一個為物件的成員或陣列的索引,第二個為對應變數或內容。如果需要退出 each 迴圈可使回撥函式返回 false,其它返回值將被忽略。

  • 引數

    • object:需要例遍的物件或陣列。
    • callback:每個成員/元素執行的回撥函式。
  • 示例

    // 例遍陣列,同時使用元素索引和內容。
    $.each( [0,1,2], function(i, n){
      alert( "Item #" + i + ": " + n );
    });
    // 例遍物件,同時使用成員名稱和變數內容。
    $.each( { name: "John", lang: "JS" }, function(i, n){
      alert( "Name: " + i + ", Value: " + n );
    });
    

2.2 建構函式的map方法

  • 語法 :jQuery.map(arr|obj,callback)

  • 返回值: Array新陣列

  • 概述

    將一個數組中的元素轉換到另一個數組中。作為引數的轉換函式會為每個陣列元素呼叫,而且會給這個轉換函式傳遞一個表示被轉換的元素作為引數。轉換函式可以返回轉換後的值、null(刪除陣列中的專案)或一個包含值的陣列,並擴充套件至原始陣列中。

  • 引數

    • array:待轉換陣列。
    • callback:為每個陣列元素呼叫,而且會給這個轉換函式傳遞一個表示被轉換的元素作為引數。函式可返回任何值。
  • 示例

    // 將原陣列中每個元素加 4 轉換為一個新陣列。
    $.map( [0,1,2], function(n){
      return n + 4;
    });
    // 結果:
    // [4, 5, 6]
    
    // 原陣列中大於 0 的元素加 1 ,否則刪除。
    $.map( [0,1,2], function(n){
      return n > 0 ? n + 1 : null;
    });
    // 結果:
    // [2, 3]
    
    // 原陣列中每個元素擴充套件為一個包含其本身和其值加 1 的陣列,並轉換為一個新陣列。
    $.map( [0,1,2], function(n){
      return [ n, n + 1 ];
    });
    // 結果:
    // [0, 1, 1, 2, 2, 3]
    

2.3 陣列的過濾方法grep

  • 語法 jQuery.grep(array, callback, [invert])

  • 概述

    使用過濾函式過濾陣列元素。此函式至少傳遞兩個引數:待過濾陣列和過濾函式。過濾函式必須返回 true 以保留元素或 false 以刪除元素。

  • 引數

    • array:待過濾陣列。

    • callback:此函式將處理陣列每個元素。第一個引數為當前元素,第二個引數而元素索引值。

    • invert:如果 "invert" 為 false 或為設定,則函式返回陣列中由過濾函式返回 true 的元素,當"invert" 為 true,則返回過濾函式中返回 false 的元素集。

  • 返回值: 陣列Array

  • 示例

    // 過濾陣列中小於 0 的元素。
    $.grep( [0,1,2], function(n,i){
      return n > 0;
    });
    // 結果:
    // [1, 2]
    
    // 排除陣列中大於 0 的元素,使用第三個引數進行排除。
    $.grep( [0,1,2], function(n,i){
      return n > 0;
    }, true);
    // 結果:
    // [0]
    

2.4 轉換陣列方法jQuery.makeArray

  • 語法:jQuery.makeArray(obj)

  • 概述

    將類陣列物件轉換為陣列物件。類陣列物件有 length 屬性,其成員索引為 0 至 length - 1。實際中此函式在 jQuery 中將自動使用而無需特意轉換。

  • 引數: obj:型別Object,類陣列物件。

  • 示例

    // 過濾陣列中小於 0 的元素。
    // <div>First</div><div>Second</div><div>Third</div><div>Fourth</div>
    
    var arr = jQuery.makeArray(document.getElementsByTagName("div"));
    arr.reverse(); // 使用陣列翻轉函式
    // 結果:
    // Fourth
    // Third
    // Second
    // First
    

2.5 陣列包含校驗inArray

  • 語法:jQuery.inArray(value,array,[fromIndex])

  • 概述

    確定第一個引數在陣列中的位置,從0開始計數(如果沒有找到則返回 -1 )。

  • 引數

    • value:用於在陣列中查詢是否存在
    • array:待處理陣列。
  • fromIndex:用來搜尋陣列佇列,預設值為0。

  • 示例

    // 檢視對應元素的位置
    var arr = [ 4, "Pete", 8, "John" ];
    jQuery.inArray("John", arr);  //3
    jQuery.inArray(4, arr);  //0
    jQuery.inArray("David", arr);  //-1
    jQuery.inArray("Pete", arr, 2);  //-1
    

2.6 合併陣列方法merge

  • 語法:jQuery.merge(first,second)

  • 概述

    合併兩個陣列返回的結果會修改第一個陣列的內容——第一個陣列的元素後面跟著第二個陣列的元素。要去除重複項,請使用$.unique()

  • 引數

    • first:第一個待處理陣列,會改變其中的元素。
    • second:第二個待處理陣列,不會改變其中的元素。
  • 示例

    // 合併兩個陣列到第一個陣列上。
    $.merge( [0,1,2], [2,3,4] )
    // 結果:
    // [0,1,2,2,3,4]
    

2.7 陣列去重unique

  • 語法:jQuery.unique(array)

  • 概述

    刪除陣列中重複元素。只處理刪除DOM元素陣列,而不能處理字串或者數字陣列。

  • 示例

    // 刪除重複 div 標籤。
    $.unique(document.getElementsByTagName("div"));
    // 結果:
    // [<div>, <div>, ...]
    

2.8 jQuery建構函式的擴充套件物件方法(繼承)

  • 語法:jQuery.extend([deep], target, object1, [objectN])

  • 概述

    用一個或多個其他物件來擴充套件一個物件,返回被擴充套件的物件。如果不指定target,則給jQuery名稱空間本身進行擴充套件。這有助於外掛作者為jQuery增加新方法。 如果第一個引數設定為true,則jQuery返回一個深層次的副本,遞迴地複製找到的任何物件。否則的話,副本會與原物件共享結構。 未定義的屬性將不會被複制,然而從物件的原型繼承的屬性將會被複制。

  • 引數

    • target:一個物件,如果附加的物件被傳遞給這個方法將那麼它將接收新的屬性,如果它是唯一的引數將擴充套件jQuery的名稱空間。
    • object1:待合併到第一個物件的物件。
    • objectN:待合併到第一個物件的物件。
    • deep:如果設為true,則遞迴合併。
  • 示例

    // 合併 settings 和 options,修改並返回 settings。
    var settings = { validate: false, limit: 5, name: "foo" };
    var options = { validate: true, name: "bar" };
    jQuery.extend(settings, options);
    // 結果:
    // settings == { validate: true, limit: 5, name: "bar" }
    

上課程式碼

// 深拷貝
var target = {name: 'laoma'};
var obj1 = {age: 18, cellphone: '18911865673', mail: '[email protected]'};
var p1 = {k: 123, m: 'abc'};
var obj2 = {run: function() { console.log(1); }, p: p1};

var newObj = jQuery.extend(true, target, obj1, obj2);
console.log(newObj, target);
console.log(newObj === target)

// console.log(newObj.p === p1);
console.log(newObj.p.k); //123
p1.k = 444; //newObj.p.k
console.log(newObj.p.k); //123
console.log('p1.k', p1.k); //444

2.9 其他建構函式上的方法和屬性

屬性名 例項 說明
noop var f = jQuery.noop; 一個空函式
isArray $.isArray([1,3,4]) 測試物件是否為陣列。
isFunction jQuery.isFunction(obj) 測試物件是否為函式。
isNumeric jQuery.isNumeric(value) 確定它的引數是否是一個數字。
isWindow jQuery.isWindow(obj) 測試物件是否是視窗
error jQuery.error(message) 接受一個字串,並且直接丟擲一個包含這個字串的異常
trim jQuery.trim(str) 去掉字串起始和結尾的空格

3.鏈式程式設計和隱式迭代

3.1 鏈式程式設計

由於大部分jQuery的api方法內部返回值都是jQuery的包裝物件自身。所以我們可以在jQuery的api呼叫之後繼續呼叫jQuery的方法,這樣就稱作是鏈式程式設計。

例如程式碼:

$('#p1').css('color', 'red').height(200).hide('slow');
// 等價於
$('#p1').css('color', 'red');
$('#p1').height(200);
$('#p1').hide('slow');

由於css方法、height、hide方法都返回jQuery包裝物件自身。所以就可以繼續鏈式呼叫。

鏈式程式設計的原理

//鏈式程式設計的原理:物件呼叫了方法後,方法返回當前物件。
var cat = {
  run: function() {
    console.log('runing');
    return this; // 核心:方法內部又把當前物件返回了。
  },
  sayHi: function() {
    console.log('hi');
    return this;
  },
  jump: function() {
    console.log('jump');
    return this;
  }
};

cat.run().sayHi().jump(); 

有些方法可以破壞鏈式的結構,比如:
nextAll(),prevAll(),sibilings(),find(),children(),parent(),parents()...

如果想回到最近一次破壞鏈式結構之前的程式碼可以使用end方法。

$('#p1').nextAll().hide().end().css('color', 'red');

3.2 隱式迭代

jQuery包裝物件本身就是一個偽陣列,匹配的元素有多個的時候,要做設定操作的時候,jQuery內部會隱式的變數所有的匹配元素呼叫設定操作,所以稱為隱式迭代。

評分控制元件案例

<ul class="list">
  <li>☆</li>
  <li>☆</li>
  <li>☆</li>
  <li>☆</li>
  <li>☆</li>
</ul>
<script src="./lib/jquery-1.12.4.js"></script>
<script>
  $(function() {
    // 第一個效果: 當滑鼠移入 五角星時候。之前的五角星和自己都變成實心的五角星
    $('.list li').hover(function(e) {
      // 滑鼠移入:當滑鼠移入 五角星時候。之前的五角星和自己都變成實心的五角星
      $(this).text('★').prevAll().text('★'); // 隱式迭代。
    }, function(e) {
      // 滑鼠移出: 把自己變成空心五角星,而且後面的也都變成空心五角星
      $(this).text('☆').nextAll().text('☆');
    }).on('click', function(e) {
      // 點選之後,記錄當前點選的是誰
      $(this).addClass('cur').siblings().removeClass('cur');
    });

    // 給整個ul標籤繫結一個mouseleave事件。
    $('.list').on('mouseleave', function(e) {
      // 拿到當前 cur 類的li標籤。
      $('.list li.cur').text('★')
          .prevAll().text('★').   // 前面的節點都設定成實心
        end().nextAll().text('☆');// 點選元素後面的節點設定成空心
    });
  });
</script>

4.jQuery的外掛封裝

4.1 給jQuery包裝物件擴充套件方法屬性

  • 直接給$.fn新增方法和屬性
(function(jQuery) {
  jQuery.fn.logText = function() {
    console.log(this.text());
  };
})(jQuery);

4.2 給建構函式擴充套件方法和屬性

  • 通過$.extend()來擴充套件jQuery建構函式
$.extend({
    log: function(message) {
        var now = new Date(),
            y = now.getFullYear(),
            m = now.getMonth() + 1, //!JavaScript中月分是從0開始的
            d = now.getDate(),
            h = now.getHours(),
            min = now.getMinutes(),
            s = now.getSeconds(),
            time = y + '/' + m + '/' + d + ' ' + h + ':' + min + ':' + s;
        console.log(time + ' My App: ' + message);
    }
});

$.log('initializing...'); //呼叫
  • 直接給jQuery建構函式新增屬性和方法
(function(jQuery) {
  jQuery.appName = 'laoma Extend';
})(jQuery);

上課案例:自定義外掛演示

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>列表切換案例</title>
  <style>
    html, body, div,  ul, li {
      padding: 0;
      margin: 0;
    }

    ul, ol {
      list-style: none;
    }

    .tab-wrap {
      border: 1px solid #ccc;
      width: 606px;
      height: 340px;
      overflow: hidden;
    }

    .tab-wrap .tab-hd {
      overflow: hidden;
    }

    .tab-wrap .tab-hd .tab-hd-item {
      float: left;
      width: 200px;
      height: 30px;
      line-height: 30px;
      background-color: #f0f0f0;
      border: 1px solid #ccc;
      text-align: center;
      cursor: pointer;
    }

    .tab-wrap .tab-hd .tab-hd-item:hover {
      background-color: #fafafa;
    }

    .tab-wrap .tab-bd .tab-bd-item {
      width: 600px;
      display: none;
    }

    .tab-wrap .tab-bd .on {
      display: block;
    }
  </style>
</head>
<body>
  <div class="tab-wrap">
    <ul class="tab-hd">
      <li class="tab-hd-item">商品1</li>
      <li class="tab-hd-item">商品2</li>
      <li class="tab-hd-item">商品3</li>
    </ul>

    <ul class="tab-bd">
      <li class="tab-bd-item on">
        <img src="./img/1.png" alt="">
      </li>
      <li class="tab-bd-item">
        <img src="./img/2.png" alt="">
      </li>
      <li class="tab-bd-item">
        <img src="./img/3.png" width="600" height="300" alt="">
      </li>
    </ul>
  </div>
  <script src="./lib/jquery-1.12.4.js"></script>
  <script>
    (function ($) {
      $.fn.lmTab = function () {
        var $hdItems = $(this).find('.tab-hd-item'),
            $bdItems = $(this).find('.tab-bd-item');
        $hdItems.on('mouseenter', function (e) {
          // 拿到當前滑鼠移入的hd部分li的索引。
          var index = $hdItems.index(this); // 獲取元素的索引。
          var bdLiDom = $bdItems.get(index); // 可以獲得第index個元素的dom物件。
          $(bdLiDom).addClass('on').siblings().removeClass('on');
        });
      };
    })(jQuery);


    $(function () {
      // 自定義外掛
      $('.tab-wrap').lmTab();  
    });
  </script>
</body>
</html>

5.jQuery常用外掛

  • jQuery UI

  • jQuery EasyUI

  • jQuery formvalidate

  • jQuery 延遲載入外掛

.....