亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

jQuery插件制作的實例教程

2019-11-20 10:02:19
字體:
來源:轉載
供稿:網友

一、jQuery插件的類型

1. jQuery方法

很大一部分的jQuery插件都是這種類型,由于此類插件是將對象方法封裝起來,在jQuery選擇器獲取jQuery對象過程中進行操作,從而發揮jQuery強大的選擇器優勢。

2. 全局函數法

可以把自定義的功能函數獨立附加到jQuery命名空間下,從而作為jQuery作用域下的一個公共函數使用。
但全局函數沒有被綁定到jQuery對象上,故不能在選擇器獲取的jQuery對象上調用。需要通過jQuery.fn()或$.fn()方式進行引用。

3. 選擇器法

如果覺得jQuery提供的選擇器不夠用或不方便的話,可以考慮自定義選擇器。

二、jQuery插件的機制

1.   jQuery.extend()方法

這種方法能夠創建全局函數或選擇器。

所謂全局函數,就是jQuery對象的方法,實際上就是位于jQuery命名空間內部的函數,有人把這類函數稱為實用工具函數,這些函數都有一個共同特征,就是不直接操作DOM元素,而是操作Javascript的非元素對象,或者執行其他非對象的特定操作,如jQuery的each()函數和noConflict()函數。

例如,在jQuery命名空間上創建兩個公共函數:


jQuery.extend({ min : function(a,b){ return a<b?a:b; }, max : function(a,b){ return a<b?b:a; } }) $(function(){ $("input").click(function(){ var a = prompt("請輸入一個數:"); var b = prompt("再輸入一個數:"); var c = jQuery.min(a,b); var d = jQuery.max(a,b); alert("最大值是:" + d + "/n最小值是:" + c); }); }) 
<input type="button" value="jQuery擴展測試" />
jQuery.extend({ min : function(a,b){ return a<b?a:b; }, max : function(a,b){ return a<b?b:a; } }) $(function(){ $("input").click(function(){ var a = prompt("請輸入一個數:"); var b = prompt("再輸入一個數:"); var c = jQuery.min(a,b); var d = jQuery.max(a,b); alert("最大值是:" + d + "/n最小值是:" + c); }); }) 
<input type="button" value="jQuery擴展測試" />

jQuery.extend()方法除了可以創建插件外,還可以用來擴展jQuery對象。

例如,調用jQuery.extend()方法把對象a和對象b合并為一個新的對象,并返回合并對象將其賦值給變量c:

var a = {name : "aaa",pass : 777}; var b = {name : "bbb",pass : 888,age : 9}; var c = jQuery.extend(a,b); $(function(){ for(var name in c){ $("div").html($("div").html() + "<br />"+ name + ":" + c[name]); } })


如果要向jQuery命名空間上添加一個函數,只需要將這個新函數制定為jQuery對象的一個屬性即可。其中jQuery對象名也可以簡寫為$,jQuery.smalluv==$.smalluv。

例如,創建jQuery全局函數:

jQuery.smalluv = { min : function(a,b){ return a<b?a:b; }, max : function(a,b){ return a<b?b:a; } } $(function(){ $("input").click(function(){ var a = prompt("請輸入一個數:"); var b = prompt("再輸入一個數:"); var c = jQuery.smalluv.min(a,b); var d = jQuery.smalluv.max(a,b); alert("最大值是:" + d + "/n最小值是:" + c); }); })


2. jQuery.fn.extend()方法

這種方法能夠創建jQuery對象方法。

舉一個最簡單的jQuery對象方法例子:

jQuery.fn.test = function(){ alert("jQuery對象方法"); } $(function(){ $("div").click(function(){ $(this).test(); }); })


三、初步總結

在jQuery匿名函數中,采用jQuery.extend();方法創建jQuery插件
在jQuery匿名函數中,采用對象.屬性=函數的方式創建jQuery插件

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html>  <head>    <title>最簡單的jquery插件</title>    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">    <script type="text/javascript" src="../res/jquery/jquery-1.4.4.min.js"></script>    <script type="text/javascript">      (function($) {        jQuery.extend({//寫法1          a: function(h){            $("#ad").html(h);          },          b:function(h){            alert(h);          }        })      })(jQuery);       (function($) {//寫法2        jQuery.a=function(h){          $("#ad").html(h);        }        jQuery.b=function(h){          alert(h);        }      })(jQuery);       $(document).ready(function(){        $.a("abc");        $.b("xyz");      });     </script>   </head>  <body>    <h3>最簡單的jQuery插件</h3>    <div id="ad"></div>  </body></html>

四、編寫實例

寫法一

插件主體:

(function($, window){  // 初始態定義  var _oDialogCollections = {};   // 插件定義  $.fn.MNDialog = function (_aoConfig) {    // 默認參數,可被重寫    var defaults = {      // string      sId : "",      // num      nWidth : 400,      // bollean      bDisplayHeader : true,      // object      oContentHtml : "",      // function      fCloseCallback : null    };     var _oSelf = this,      $this = $(this);     // 插件配置    this.oConfig = $.extend(defaults, _aoConfig);     // 初始化函數    var _init = function () {      if (_oDialogCollections) {        // 對于已初始化的處理        // 如果此時已經存在彈框,則remove掉再添加新的彈框      }      // 初始化彈出框數據      _initData();      // 事件綁定      _loadEvent();      // 加載內容      _loadContent();          }    // 私有函數    var _initData = function () {};    var _loadEvent = function () {};    var _loadContent = function () {      // 內容(分字符和函數兩種,字符為靜態模板,函數為異步請求后組裝的模板,會延遲,所以特殊處理)      if($.isFunction(_oSelf.oConfig.oContentHtml)) {        _oSelf.oConfig.oContentHtml.call(_oSelf, function(oCallbackHtml) {          // 便于傳帶參函數進來并且執行          _oSelf.html(oCallbackHtml);          // 有回調函數則執行          _oSelf.oConfig.fLoadedCallback && _oSelf.oConfig.fLoadedCallback.call(_oSelf, _oSelf._oContainer$);        });      } else if ($.type(_oSelf.oConfig.oContentHtml) === "string") {        _oSelf.html(_oSelf.oConfig.oContentHtml);        _oSelf.oConfig.fLoadedCallback && _oSelf.oConfig.fLoadedCallback.call(_oSelf, _oSelf._oContainer$);      } else {        console.log("彈出框的內容格式不對,應為function或者string。");      }    };     // 內部使用參數    var _oEventAlias = {      click     : 'D_ck',      dblclick   : 'D_dbl'    };     // 提供外部函數    this.close = function () {      _close();    }         // 啟動插件    _init();     // 鏈式調用    return this;      };  // 插件結束})(jQuery, window);

調用

var MNDialog = $("#header").MNDialog({  sId : "#footer",    //覆蓋默認值  fCloseCallback : dialog,//回調函數  oContentHtml : function(_aoCallback){      _aoCallback(_oEditGrpDlgView.el);    }  }});// 調用提供的函數MNDialog.close;function dialog(){ }

點評

1. 自調用匿名函數

(function($, window) { // jquery code})(jQuery, window);

用處:通過定義一個匿名函數,創建了一個“私有”的命名空間,該命名空間的變量和方法,不會破壞全局的命名空間。這點非常有用也是一個JS框架必須支持的功能,jQuery被應用在成千上萬的JavaScript程序中,必須確保jQuery創建的變量不能和導入他的程序所使用的變量發生沖突。

2. 匿名函數為什么要傳入window

通過傳入window變量,使得window由全局變量變為局部變量,當在jQuery代碼塊中訪問window時,不需要將作用域鏈回退到頂層作用域,這樣可以更快的訪問window;這還不是關鍵所在,更重要的是,將window作為參數傳入,可以在壓縮代碼時進行優化,看看jquery.min.js:

(function(a,b){})(jQuery, window); // jQuery被優化為a, window 被優化為 b

3. 全局變量this定義

var _oSelf = this,$this = $(this);

使得在插件的函數內可以使用指向插件的this

4. 插件配置

this.oConfig = $.extend(defaults, _aoConfig);

設置默認參數,同時也可以再插件定義時傳入參數覆蓋默認值

5. 初始化函數

一般的插件會有init初始化函數并在插件的尾部初始化

6. 私有函數、公有函數

私有函數:插件內使用,函數名使用”_”作為前綴標識

共有函數:可在插件外使用,函數名使用”this.”作為前綴標識,作為插件的一個方法供外部使用

7. return this

最后返回jQuery對象,便于jQuery的鏈式操作

寫法二

主體結構

(function($){  $.fn.addrInput = function(_aoOptions){    var _oSelf = this;    _oSelf.sVersion = 'version-1.0.0';    _oSelf.oConfig = {      nInputLimitNum : 9    };    // 插件配置    $.extend(_oSelf.oConfig, _aoOptions);     // 調用這個對象的方法,傳遞this    $.fn.addrInput._initUI.call(_oSelf, event);    $.fn.addrInput._initEvents.call(_oSelf);     // 提供外部函數    this.close = function () {      _close();    }     //返回jQuery對象,便于Jquery的鏈式操作      return _oSelf;            }  $.fn.addrInput._initUI = function(event){    var _oSelf = this,      _oTarget = $(event.currentTarget);  }  $.fn.addrInput._initEvents = function(){}})(window.jQuery);

點評

1. 美觀

插件的方法寫在外部,并通過在插件主體傳遞this的方式調用

2. 定義插件版本號

不過在這里還是沒有用到

3. 關于call

這里的第一個參數為傳遞this,后面的均為參數

語法:

call([thisObj[,arg1[, arg2[, [,.argN]]]]])
定義:調用一個對象的一個方法,以另一個對象替換當前對象。

說明:call 方法可以用來代替另一個對象調用一個方法。call 方法可將一個函數的對象上下文從初始的上下文改變為由 thisObj 指定的新對象。如果沒有提供 thisObj 參數,那么 Global 對象被用作 thisObj。

4. 關于”this”

在插件的方法中,可能有用到指向插件的this、和指向事件觸發的this,所以事件觸發的this用event來獲取:event.cuerrntTarget

event.currentTarget:指向事件所綁定的元素,按照事件冒泡的方式,向上找到元素
event.target:始終指向事件發生時的元素
如:

html代碼

<div id="wrapper">   <a href="#" id="inner">click here!</a> </div>

 js代碼

$('#wrapper').click(function(e) {   console.log('#wrapper');   console.log(e.currentTarget);   console.log(e.target); }); $('#inner').click(function(e) {   console.log('#inner');   console.log(e.currentTarget);   console.log(e.target); });

結果輸出

#inner<a href=​"#" id=​"inner">​click here!​</a>​<a href=​"#" id=​"inner">​click here!​</a>​#wrapper<div id=​"wrapper">​<a href=​"#" id=​"inner">​click here!​</a>​</div>​<a href=​"#" id=​"inner">​click here!​</a>​

寫法三(原生寫法)

主體結構

var MemberCard = function(_aoOption){  // 配置(默認是從外面傳進來)  _aoOption || (_aoOption = {}) ;  // 初始化函數  _init(this);} var _init = function(_aoSelf) {  // 函數執行  _initData(_aoSelf);  // 調用對象的私有方法  _aoSelf._timedHide();} var _initData = function ( _aoSelf ) {} // 私有方法MemberCard.prototype._timedHide = function(_aoOptions) {  var _oSelf = this;  clearTimeout(this.iHideTimer);    // 使用underscore.js的extend方法來實現屬性覆蓋  var oDefault = extend( { nHideTime: 300 }, _aoOptions );  _oSelf.iHideTimer = setTimeout( function(){    // 調用對象的共有方法    _oSelf.hide();  }, oDefault.nHideTime);    } // 公有方法MemberCard.prototype.hide = function(_aoOptions) {}

使用

var oColleagueCard = new MemberCard({ nHideTime: 200 });oColleagueCard.hide();

點評:

1. 關于屬性覆蓋(對象深拷貝)

原生函數實現方法

function getType(o){  return ((_t = typeof(o)) == "object" ? o==null && "null" || Object.prototype.toString.call(o).slice(8,-1):_t).toLowerCase();}function extend(destination,source){  for(var p in source){    if(getType(source[p])=="array"||getType(source[p])=="object"){      destination[p]=getType(source[p])=="array"?[]:{};      arguments.callee(destination[p],source[p]);    }else{      destination[p]=source[p];    }  }}

demo:

var test={a:"ss",b:[1,2,3],c:{d:"css",e:"cdd"}};var test1={};extend(test1,test);test1.b[0]="change"; //改變test1的b屬性對象的第0個數組元素alert(test.b[0]); //不影響test,返回1alert(test1.b[0]); //返回change

基于jQuery的實現方法:

jQuery.extend([deep], target, object1, [objectN]);

用一個或多個其他對象來擴展一個對象,返回被擴展的對象。

如果不指定target,則給jQuery命名空間本身進行擴展。這有助于插件作者為jQuery增加新方法。 如果第一個參數設置為true,則jQuery返回一個深層次的副本,遞歸地復制找到的任何對象。否則的話,副本會與原對象共享結構。 未定義的屬性將不會被復制,然而從對象的原型繼承的屬性將會被復制。

demo:

var options = {id: "nav", class: "header"}var config = $.extend({id: "navi"}, options); //config={id: "nav", class: "header"}

 2. 關于this

這個對象的所有方法的this都指向這個對象,所以就不需要重新指定

寫法四

主體結構

function EditorUtil() {  this._editorContent = $( '#editor_content' );  this._picBtn = $( '#project_pic' );  this.ieBookmark = null;}EditorUtil.prototype = {  consturctor: EditorUtil,   noteBookmark: function() {  },  htmlReplace: function( text ) {    if( typeof text === 'string' ) {      return text.replace( /[<>"&]/g, function( match, pos, originalText ) {        switch( match ) {          case '<':            return '<';          case '>':            return '>';          case '&':            return '&';          case '"':            return '"';        }      });    }    return '';  },  init: function() {    this._memBtn.bind( 'click', function( event ) {      $(".error_content").hide();      return false;    });  }}; // 初始化富文本編輯器var editor = new EditorUtil();editor.init();

總結

寫法四和寫法三其實都差不多,但是你們有沒有看出其中的不一樣呢?

兩種都是利用原型鏈給對象添加方法:

寫法三:

MemberCard.prototype._timedHideMemberCard.prototype.hide

寫法四:

EditorUtil.prototype = {  consturctor: EditorUtil,  noteBookmark: function(){},    htmlReplace: function(){}}

細看寫法四利用“對象直接量”的寫法給EditorUtil對象添加方法,和寫法三的區別在于寫法四這樣寫會造成consturctor屬性的改變

constructor屬性:始終指向創建當前對象的構造函數

每個函數都有一個默認的屬性prototype,而這個prototype的constructor默認指向這個函數。如下例所示:

function Person(name) {   this.name = name; }; Person.prototype.getName = function() {   return this.name; }; var p = new Person("ZhangSan"); console.log(p.constructor === Person); // true console.log(Person.prototype.constructor === Person); // true // 將上兩行代碼合并就得到如下結果 console.log(p.constructor.prototype.constructor === Person); // truefunction Person(name) {   this.name = name; }; Person.prototype.getName = function() {   return this.name; }; var p = new Person("ZhangSan");  console.log(p.constructor === Person); // true console.log(Person.prototype.constructor === Person); // true // 將上兩行代碼合并就得到如下結果 console.log(p.constructor.prototype.constructor === Person); // true當時當我們重新定義函數的prototype時(注意:和上例的區別,這里不是修改而是覆蓋),constructor屬性的行為就有點奇怪了,如下示例:function Person(name) {   this.name = name; }; Person.prototype = {   getName: function() {     return this.name;   } }; var p = new Person("ZhangSan"); console.log(p.constructor === Person); // false console.log(Person.prototype.constructor === Person); // false console.log(p.constructor.prototype.constructor === Person); // false

為什么呢?

原來是因為覆蓋Person.prototype時,等價于進行如下代碼操作:

Person.prototype = new Object({   getName: function() {     return this.name;   } });Person.prototype = new Object({   getName: function() {     return this.name;   } });


而constructor屬性始終指向創建自身的構造函數,所以此時Person.prototype.constructor === Object,即是:

function Person(name) {   this.name = name; }; Person.prototype = {   getName: function() {     return this.name;   } }; var p = new Person("ZhangSan"); console.log(p.constructor === Object); // true console.log(Person.prototype.constructor === Object); // true console.log(p.constructor.prototype.constructor === Object); // truefunction Person(name) {   this.name = name; }; Person.prototype = {   getName: function() {     return this.name;   } }; var p = new Person("ZhangSan"); console.log(p.constructor === Object); // true console.log(Person.prototype.constructor === Object); // true console.log(p.constructor.prototype.constructor === Object); // true


怎么修正這種問題呢?方法也很簡單,重新覆蓋Person.prototype.constructor即可:

function Person(name) {   this.name = name; }; Person.prototype = new Object({   getName: function() {     return this.name;   } }); Person.prototype.constructor = Person; var p = new Person("ZhangSan"); console.log(p.constructor === Person); // true console.log(Person.prototype.constructor === Person); // true console.log(p.constructor.prototype.constructor === Person); // truefunction Person(name) {   this.name = name; }; Person.prototype = new Object({   getName: function() {     return this.name;   } }); Person.prototype.constructor = Person; var p = new Person("ZhangSan"); console.log(p.constructor === Person); // true console.log(Person.prototype.constructor === Person); // true console.log(p.constructor.prototype.constructor === Person); // true


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久久天堂国产精品女人| 在线精品视频视频中文字幕| 亚洲人成在线播放| 欧美另类极品videosbestfree| 日本午夜精品理论片a级appf发布| 国产主播喷水一区二区| 亚洲日韩欧美视频| 国产精品丝袜高跟| 日韩电影大片中文字幕| 精品成人69xx.xyz| 国产精品久久久久久网站| 亚洲人成在线观看网站高清| 久久精品成人欧美大片| 国产精品自拍偷拍视频| 中文字幕视频在线免费欧美日韩综合在线看| 精品久久久一区| 国产视频精品久久久| 国产欧美一区二区三区在线看| 国产欧美一区二区三区视频| 日本精品久久久久影院| 91啪国产在线| 成人在线小视频| 国产精品久久久久久久久久久久久久| 亚洲大尺度美女在线| 精品一区二区亚洲| 久久香蕉国产线看观看av| 亚洲第一区第一页| 在线视频中文亚洲| 国产一区二区激情| 国产精品av在线| 欧美电影院免费观看| 亚洲欧洲在线播放| 久久久精品国产一区二区| 亚洲最大福利视频网| 欧美黑人xxxⅹ高潮交| 国产美女精品免费电影| 国产精品91一区| 日韩在线播放一区| 亚洲天堂视频在线观看| 亚洲精品美女久久久| 成人激情视频小说免费下载| 国产成人91久久精品| 日韩电影大片中文字幕| 国产香蕉精品视频一区二区三区| 日韩在线观看网址| 成人动漫网站在线观看| 成人午夜激情网| 欧美国产第二页| 高清日韩电视剧大全免费播放在线观看| 欧美一级黄色网| 久久久久久久久久久免费| 国产精品激情av在线播放| 成人激情在线播放| 国产成人av网址| 国产成人福利夜色影视| 亚洲午夜未删减在线观看| 日韩动漫免费观看电视剧高清| 精品成人国产在线观看男人呻吟| 亚洲第一页在线| 欧美成aaa人片在线观看蜜臀| 一区二区三区视频观看| 最近2019中文字幕一页二页| 国产日韩中文字幕在线| 国产精品久久综合av爱欲tv| 国产一区二中文字幕在线看| 91高清视频免费| 久久影院在线观看| 欧美在线视频一二三| 狠狠躁18三区二区一区| 午夜欧美不卡精品aaaaa| 国产精品69精品一区二区三区| 欧美成人免费播放| 精品久久久久久久久久国产| 色天天综合狠狠色| 中文字幕日韩专区| 精品欧美一区二区三区| 97人人模人人爽人人喊中文字| 青青草99啪国产免费| 欧美另类在线观看| 久久夜色精品国产亚洲aⅴ| 亚洲天堂视频在线观看| 国产精品免费看久久久香蕉| 欧美激情一区二区三区在线视频观看| 欧美肥老妇视频| 亚洲一区二区三区视频播放| 国产精品一区二区在线| 欧美高清第一页| 搡老女人一区二区三区视频tv| 亚洲精品黄网在线观看| 91精品国产自产在线| 91精品免费久久久久久久久| 久久久亚洲欧洲日产国码aⅴ| 久久亚洲精品中文字幕冲田杏梨| 中文字幕一区二区三区电影| 久久天天躁夜夜躁狠狠躁2022| 久久久久久这里只有精品| 国产精品福利在线| 欧美性感美女h网站在线观看免费| 日韩高清免费观看| 亚洲性生活视频在线观看| 最新国产成人av网站网址麻豆| 亚洲自拍高清视频网站| 日韩中文字幕在线免费观看| 久久噜噜噜精品国产亚洲综合| 国产精品久久久久久久美男| 欧美激情视频播放| 亚洲精品小视频在线观看| 日韩av高清不卡| 国产一区二区久久精品| 一区二区三欧美| 中日韩美女免费视频网站在线观看| 欧美日韩高清在线观看| 国产91精品青草社区| 欧美日韩第一视频| 国产欧美日韩最新| 亚洲日本成人女熟在线观看| 久久久久久尹人网香蕉| 日韩有码片在线观看| 九九精品在线播放| 亚洲人成啪啪网站| 日本韩国在线不卡| 国产精品一区二区性色av| 国产美女91呻吟求| 欧洲午夜精品久久久| 久久精品国产亚洲| 国产精品欧美久久久| 亚洲自拍偷拍福利| 国产视频久久久| 欧美激情国内偷拍| 国产成人精品国内自产拍免费看| 欧美黄色三级网站| 国产视频精品久久久| 亚洲色在线视频| 综合久久五月天| 日本成人在线视频网址| 欧美成人午夜激情在线| 亚洲国产高清自拍| 久久中文字幕在线视频| 亚洲国产日韩精品在线| 日韩精品视频三区| 久久影院在线观看| 2020久久国产精品| 91在线免费观看网站| 成人黄色午夜影院| 日韩av中文字幕在线免费观看| 国产欧美一区二区三区在线看| 欧美在线视频免费播放| 尤物yw午夜国产精品视频明星| 亚洲色图五月天| 亚洲欧洲国产伦综合| 国产精品亚洲片夜色在线| 欧美精品videosex牲欧美| 在线播放国产一区二区三区| 日韩av不卡电影| 国产91在线播放九色快色| 亚洲国产成人精品久久久国产成人一区| 欧美伊久线香蕉线新在线| 久久精品国产v日韩v亚洲| 欧美一级大片在线免费观看| 国外视频精品毛片| 少妇高潮久久久久久潘金莲| 自拍偷拍免费精品| 7777精品视频| 国产精品永久免费观看|