《鋒利的jQuery(第2版)》jQuery核心原理及插件編寫

前六章的內容在上一篇文章中已有介紹,后面的內容主要是一些JQuery的插件的介紹,有一些感覺是很有用的,但是有一些個人覺得構建一個功能需要引入2-3個插件,就有點累贅,所以我覺得學會先學會如何編寫插件才是最適合自己的方法,今天根據書中內容結合自己的理解說說jQuery插件的編寫。

jQuery核心原理

我們通過jQuery()函數可以得到一個jQuery對象,但是實際上,我們得到的jQuery對象并不是jQuery()這個函數創造出來的對象,在這個函數中,原理是

jQuery(){
     return  new  jQuery.fn.init()
}
05jQuery源碼截取.jpg

在jQuery的原型對象有兩個名字,jQuery.prototype == jQuery.fn。jQuery的原型對象有一個constructor屬性,又指回了jQuery,jQuery的原型對象還有一個init屬性,這個init屬性才是真正的構造函數,jQuery原型對象上還有一些first(),last(),eq()等函數,我們知道,每一個函數都有一個prototype指針指向原型對象,每一個原型對象都有一個constructor指針指回構造函數,構造函數創建出來的實例對象,都可以使用原型對象中封裝的屬性和方法。也就是說,通過jQuery.fn.init()創建出來的對象,都可以使用eq(),first(),last()等函數,因為jQuery的原型對象上就有這些方法,那么我們直接把jQuery.fn.init.prototype = jQuery.fn = jQuery.prototype,那么init函數創建出來的對象,就可以使用這些方法了。

總結起來就是說,jQuery的原型對象jQuery.prototypr中有一個init屬性,它才是真正的構造函數,這個構造函數的原型對象又指回了jQuery的原型對象jQuery.prototypr,所以init創建出來的對象,就可以使用jQuery原型對象上的方法。因為init和jQuery的原型對象都是jQuery.prototype,所以init和jQuery創建出來的對象理解上去應該是一樣的。

以下為jQuery源碼截取。

06.jpg
07.jpg

關于鏈式語法

jQuery中比較經典的還有就是鏈式語法,它的實現原理是啥呢?

在每一個jQuery對象方法的末尾,都返回這個對象,那么即可實現鏈式語法。也就是return this、

08jQuery源碼截取.jpg

那么我們模擬一下這個鏈式語法

    <script type="text/javascript">
        function Person(){
            this.name = "小飯";
        }
        Person.prototype.study = function(){
            console.log("飯飯愛學習");
            return this;//鏈式語法的核心
        }
        Person.prototype.eat = function(){
            console.log("飯飯愛吃飯");
            return this;
        }

        var Luckfine = new Person();
        console.log( Luckfine.study() === Luckfine );

        Luckfine.study().eat()

        /*
        jQuery的核心原理 jQuery.fn.init.prototype == jQuery.prototype
        jQuery的鏈式語法 return this;
        */
        
    </script>

運行結果

09.jpg

jQuery === $

在實際使用的時候我們通常是用$來代替jQuery,那么我們是如何實現的呢?

10jQuery源碼截取.jpg

所以就是說jQuery還有個名字叫$.

jQuery插件的基本要點

1、jQuery插件的文件名推薦為jQuery.[插件名].js,一面和其他JavaScript庫插件混淆,例如:jQuery.color.js
2、所有對象方法都應當附加到jQuery.fn對象上,而所有的全局函數都應該附加到jQuery對象本身上
3、在插件內部,this指向的是當前通過選擇器獲取的jQuery對象,而不是像一般方法那樣,例如click()方法,內部this指向的是DOM元素。
4、可以通過this.each來遍歷所有元素
5、所有的方法或函數插件,都應當以分號結尾,否則壓縮的時候可能會出現問題,為了更穩妥一些,甚至可以在插件頭部先加一個分號,以免他人的不規范代碼給插件帶來的影響。
6、插件應該返回一個jQuery對象,以保障插件可以鏈式操作,除非插件需要返回的是一些需要獲取的量,例如字符串或者數組等
7、避免在插件內部使用$作為jQuery對象的別名,而應使用完整的jQuery來表示,這樣可以避免沖突,當然,也可以利用歐冠必報這種技巧來避免這個問題,使插件內部繼續使用$作為jQuery的別名,很多插件都是這么做的

插件的形式

通過jQuery源碼我們能夠看到,jQuery整體就是模仿一個塊級作用域,也就是整體在一個立即執行函數中書寫的,這樣也防止了用戶自己定義的變量和jQuery定義的變量沖突。這種也是利用閉包,顯然閉包不是幾句話就能講清楚的,我們就理解這是一個塊級作用域就好了。

01.jpg

那么我們在封裝自己的jQuery插件的時候,就可以采用這種形式,首先定義一個匿名函數function ( ) { //這里放置代碼 },將其插入到一個立即執行函數中 (function ( ) { //這里放置代碼})(),在第二個括號中,可以將參數傳遞進去,以供函數內部使用。

//為了更好的兼容性,開始前可以有個分號
;( function ( $ ) { //此處將$作為匿名函數的形參
    //這里放置代碼,可以使用$作為jQuery的縮寫別名
} )( jQuery )  //這里就將jQuery作為實參傳遞給匿名函數了。

jQuery插件的機制

jQuery提供了兩個用于擴展jQuery功能的方法,即jQuery.fn,extend( ) 和 jQuery.extend ( ) 方法、前者用于擴展對象方法的插件,后者用于封裝全局函數的插件。這兩種方法都接受一個參數,類型為object,object對象的“名/值對”分別代表“函數或方法名/函數主體”,具體內容會在下面講解。

編寫jQuery對象插件

1.編寫設置和獲取顏色的插件

該插件有兩個功能
a,設置匹配元素的顏色
b,獲取匹配的元素(元素集合中的第一個)的顏色

由于是對jQuery對象的方法的擴展,因此采用jQuery.fn.extend( )來編寫,可以給這個方法提供一個參數value,如果調用方法的時候傳遞了value這個參數,那么就是這個值來設置字體顏色,否則就是獲取匹配元素的字體顏色的值。
首先,我們要知道,簡單的調用jQuery提供的css() 方法,直接寫成this.css("color","value")即可。注意,插件內部的this指向的是jQuery對象,而非普通的DOM對象,接下來需要注意的是,插件如果不需要返回字符串之類的特定值,應當使其具有可鏈接性,為此,直接返回這個this對象,由于css()方法會直接返回調用它的對象,那么我 們直接return this.css("color","value")即可。

接下來第二個功能,如果沒有給方法傳遞參數,那么就是獲取集合對象對象中第一個對象的color的值,由于css()本身就有返回第一個匹配元素的樣式值得功能,因此此處無需用eq()來回去第一個元素,只要將這兩個功能 結合起來,判斷一下value是否是undefined即可。

        <script src="jquery/jquery-3.0.0.min.js"></script>
        <script type="text/javascript">
            ;(function($){
                jQuery.fn.extend({
                    "color":function(value){
                        if(value == undefined){
                            return this.css("color");
                        }else{
                            return this.css("color",value);                 
                        }
                    }
                })
            })(jQuery)
        </script>

測試一下該插件

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
        <div class="a">red</div>
        <div class="blue">blue</div>
        <div style="color: green;">green</div>
        <div style="color: yellow;">yellow</div>
        <script src="jquery/jquery-3.0.0.min.js"></script>
        <script type="text/javascript">
            ;(function($){
                jQuery.fn.extend({
                    "color":function(value){
                        if(value == undefined){
                            return this.css("color");
                        }else{
                            return this.css("color",value);                 
                        }
                    }
                })
            })(jQuery)
        </script>
        <script>
            $(function(){
                //查看第一個div的color樣式
                alert($('div').color())
                //返回的object證明得到的jQuery對象
                alert($('div').color('red'))
                //把所有的div的字體顏色都設為紅色,證明插件好
                $('div').color("red")
            })
        </script>
    </body>
</html>

測試效果


GIF.gif
2、編寫插件實現點擊標簽改變標簽的背景色
    $.fn.extend({
            clcikChangeBg:function(){
                this.on("click",function(){
                    $(this).css("background-color","red");  
                    $(this).siblings().css("background-color","#fff");
                })
                
            }
        })

        $("div").clcikChangeBg();

插件效果

GIF.gif
3、編寫插件實現單擊雙擊

功能如下:
a,區分單擊雙擊
b,單擊改變顏色,雙擊時候不觸發單擊,只允許隱藏

jQuery.fn.extend({
    myClick:function(){
        var timer;
        this.on("click",function(){
            clearTimeout(timer);
            var _this=$(this)
            timer = setTimeout(function(){
                _this.siblings().css("background-color","blue")
                _this.css("background-color","orange")
            },200)
        })
            .on("dblclick",function(){
                clearTimeout(timer);
                $(this).css("background-color","blue")
                $(this).fadeOut(800);               
        })
    }

})

$("div").myClick()

效果如下

GIF.gif

編寫jQuery全局插件

這類插件是在jQuery命名空間內部添加一個函數,這類插件很簡單,只是普通的函數,利用jQuery.extend( )方法直接對jQuery對象進行擴展。

1.編寫插件實現過濾敏感字

$.extend({
            filterWord:function(str){
                var keyWords = ["臺獨","藏獨","國民黨"];
                for (var i = 0; i < keyWords.length; i++) {
                    
                    // str = str.replace(keyWords[i],"***");
                    var r = new RegExp(keyWords[i],"g"); //  /臺獨/g
                    str = str.replace( r,"***")
                }

                return str;
                
            }
        });

        console.log( $.filterWord("臺獨規劃局規劃臺獨藏獨藏獨國民黨是什么") );

效果如下

02.jpg

重點

添加到$.extend( ) 上的是全局函數:添加到jQuery.fn.extend( )上的是原型對象上的函數,需要通過jQuery的對象來調用。

編寫插件實現把集合轉換成真正的數組

都知道如果我們jQuery選擇器獲取到的是一個集合,并不是一個數組,如果我們把獲取的集合轉換成數組,那么我們就可以直接使用數組中自帶的方法操作我們的對象,豈不是很方便。

封裝在全局函數中

        $.extend({
            makeRealArray:function($Arr){
                var arr = [];
                for (var i = 0; i < $Arr.length; i++) {
                    arr.push(  $Arr[i] ); 
                }
                return arr;
            }
        })
        var ret = $.makeRealArray( $("div")  )
        console.log(ret);//打印這個數組
        console.log( Array.isArray(ret) );//判斷對象是否是數組

效果如下

03.jpg

封裝成對象方法

        $.fn.extend({
            toArray_My:function(){
                var arr = [];
                this.each(function(index,element){
                    arr.push(element);
                })
                return arr;
            }
        })
        console.log( $("div").toArray_My()  );

效果如下

04.jpg

兩個方法都是將獲取到的集合轉換成數組,但是封裝的形式不一樣,所以調用的方法是不一樣的,要注意區分。

自己把書看了一遍,結合自己的理解,整理成文章,真是一個耗時的過程。也建議正在看這本書的孩子把里面的例子自己敲一下,會發現里面的有些例子擴展性很強。

喜歡小飯的文章就點贊啦啦拉票啦~

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,460評論 6 538
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,067評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,467評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,468評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,184評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,582評論 1 325
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,616評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,794評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,343評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,096評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,291評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,863評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,513評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,941評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,190評論 1 291
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,026評論 3 396
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,253評論 2 375

推薦閱讀更多精彩內容