一、jQuery 提供開發者開發插件的幾種模式 1.$.extend(); //這個方法是綁定在$上面的。可以通過$直接調用 2.$.fn.方法名 //這個方法是綁定在Dom對象上面的可以通過$('').方法名();調用 3.$.widget //通過jQuery UI 部件工廠模式創建。 二、插件 ...
一、jQuery 提供開發者開發插件的幾種模式
1.$.extend(); //這個方法是綁定在$上面的。可以通過$直接調用
2.$.fn.方法名 //這個方法是綁定在Dom對象上面的可以通過$('').方法名();調用
3.$.widget //通過jQuery UI 部件工廠模式創建。
二、插件的開發過程
1.$.extend();
這個方法其實很簡單,只是像$上面添加了一個靜態的方法而已。主要用途是對插件api的擴展.
eg:
//$.extend();為了防止,變數和方法之間的相互污染,我們採用閉包的模式。 (function($,factory){ var obj = factory(); $.extend({ sayHelloWorld:obj.firstApply, }) $.secondApply = obj.secondApply; })(jQuery,function(){ var obj = { firstApply(){ console.log('hello world'); }, secondApply(){ console.log('直接綁定到$上'); }, }; return obj; }); $.sayHelloWorld();//hello world $.secondApply(); //直接綁定到$上 /*從上面的2種綁定方式可以看出用$.extend();對jQuery方法進行拓展, 其實和直接綁定到$上是一樣的效果*/
2.$.fn.方法名。 (方法名 其實就是插件名)。
a.插件結構
<div id="app">app</div> //$.fn.插件名字 (logText); (function($,factory){ $.fn.logText = factory(); })(jQuery,function(){ var logText = function(){ console.log(this.text()); return this; } return logText; }); $("#app").logText(); //app 通過DOM元素之間調用該方法。並返回該對象。這也是jQuery實現鏈式操作的技巧。 var h = $("#app").logText().height(); // app console.log(h); //18 //這樣就可以自定義方法了。
在jQuery插件的開發過程中,其實主要是通過第二種模式($.fn.插件名)開發的。因為jQuery的強大之處就是對Dom的操作.
b.一個插件的強大之處就是參提供周全的參數。以及方便使用者對參數進行擴展。
<div id="app">app</div> //$.fn.插件名字 (myPuglin); (function(global,$,factory){ var common = factory(); //封裝插件使用到的函數。 $.fn.myPuglin = function(opts){ //插件的名稱 var defaults = {}; //預設的api opts = $.extend(defaults,opts || {}); //對api的拓展 /* * * 要執行的功能 * */ console.log(opts.hello); return this; } })(window,jQuery,function(){ var common = { a(opt){ return opt; }, }; return common; }); $("#app").myPuglin({hello:'hello world'}); //hello world
準備工作已經完畢。那麼下麵會一個插件為列子,來講解
3.工作中經常用到的列表到詳情。返回來需要保留該位置的插件。(返回定位) savePositon(); $.fn.savePosition
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"> <title>Title</title> <style> @media screen and (max-width: 319px) { html { font-size: 85.33333px; } } @media screen and (min-width: 320px) and (max-width: 359px) { html { font-size: 85.33333px; } } @media screen and (min-width: 360px) and (max-width: 374px) { html { font-size: 96px; } } @media screen and (min-width: 375px) and (max-width: 383px) { html { font-size: 100px; } } @media screen and (min-width: 384px) and (max-width: 399px) { html { font-size: 102.4px; } } @media screen and (min-width: 400px) and (max-width: 413px) { html { font-size: 106.66667px; } } @media screen and (min-width: 414px) { html { font-size: 110.4px; } } /*CSS Reset*/ body, div, dl, dt, dd, ul, ol, li, h1, h2, h3, h4, h5, h6, pre, code, form, fieldset, legend, input, textarea, p, blockquote, th, td, header, hgroup, nav, section, article, aside, footer, figure, figcaption, menu, button { margin: 0; padding: 0; } li{ list-style: none; } #app{ width: 100%; max-width: 640px; } li { height: 1.2rem; width: 100%; border-bottom: 1px solid #cccccc; text-align: center; line-height: 1.2rem; font-size: 20px; } </style> <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script> </head> <body> <div id="app"> <ul> <li data-page="1" data-url="http://baidu.com?id=1">第一頁 第1個li</li> <li data-page="1" data-url="http://baidu.com?id=2">第一頁 第2個li</li> <li data-page="1" data-url="http://baidu.com?id=3">第一頁 第3個li</li> <li data-page="1" data-url="http://baidu.com?id=4">第一頁 第4個li</li> <li data-page="1" data-url="http://baidu.com?id=5">第一頁 第5個li</li> <li data-page="1" data-url="http://baidu.com?id=6">第一頁 第6個li</li> <li data-page="1" data-url="http://baidu.com?id=7">第一頁 第7個li</li> <li data-page="1" data-url="http://baidu.com?id=8">第一頁 第8個li</li> <li data-page="1" data-url="http://baidu.com?id=9">第一頁 第9個li</li> <li data-page="1" data-url="http://baidu.com?id=10">第一頁 第10個li</li> <li data-page="1" data-url="http://baidu.com?id=11">第一頁 第11個li</li> <li data-page="1" data-url="http://baidu.com?id=12">第一頁 第12個li</li> <li data-page="1" data-url="http://baidu.com?id=13">第一頁 第13個li</li> <li data-page="1" data-url="http://baidu.com?id=14">第一頁 第14個li</li> <li data-page="1" data-url="http://baidu.com?id=15">第一頁 第15個li</li> <li data-page="2" data-url="http://baidu.com?id=16">第二頁 第1個li</li> <li data-page="2" data-url="http://baidu.com?id=17">第二頁 第2個li</li> <li data-page="2" data-url="http://baidu.com?id=18">第二頁 第3個li</li> <li data-page="2" data-url="http://baidu.com?id=19">第二頁 第4個li</li> <li data-page="2" data-url="http://baidu.com?id=20">第二頁 第5個li</li> <li data-page="2" data-url="http://baidu.com?id=21">第二頁 第6個li</li> <li data-page="2" data-url="http://baidu.com?id=22">第二頁 第7個li</li> <li data-page="2" data-url="http://baidu.com?id=23">第二頁 第8個li</li> <li data-page="2" data-url="http://baidu.com?id=24">第二頁 第9個li</li> <li data-page="2" data-url="http://baidu.com?id=25">第二頁 第10個li</li> <li data-page="2" data-url="http://baidu.com?id=26">第二頁 第11個li</li> <li data-page="2" data-url="http://baidu.com?id=27">第二頁 第12個li</li> <li data-page="2" data-url="http://baidu.com?id=28">第二頁 第13個li</li> <li data-page="2" data-url="http://baidu.com?id=29">第二頁 第14個li</li> <li data-page="2" data-url="http://baidu.com?id=30">第二頁 第15個li</li> </ul> </div> </body> <script type="text/javascript"> /* * 1.為什麼我要返回定位呢。肯定是增加用戶的體驗度。比如你剛看的那條信息挺感 * 興趣的,點進詳情看完了,回來一看,不見了,是不是很嘔心啊。 * 2.難點在哪裡? * 難點1:當我們有很多的列表的時候,列表肯定是滾動載入。於是我們直接保存滾動條的位置 * 的方式可以放棄了。 * 難點2:我們怎麼確定是從詳情返回來的? * 3.我們該怎麼實現呢? * 其實我們實現的方式跟保存滾動條的位置差不多。但要對scrollTop的距離進行處理。 * a.我們點擊這點詳情的時候,可視區域列表的條數,可以是一頁的數據,可能會是2頁數據。 * 這種情況下我們都要把結果保留下來。 * b.當我們點擊這條數據的時候存現當前頁滾動了多少就可以了。 * * 下麵具體看代碼: */ (function(global,$,factory){ var keepScrollTop = 0; //用於最後保存的滾動條的位置 var tool =factory(); $.fn.savePosition = function(options){ var dataPage,logo,objLogo,prevNum,containerHeight = 0,scrollTopDistance = 0,elIndex = 0, prevHeight = 0,prevCountPage = 0,prevCountPageDistance = 0,prevDistance = 0, prevPageScrollDistance = 0; var elements = this; var defaults = { container:$(window), //滾動的容器 logo:"data-url", // 用於計算在這個容器中的每個LI中的唯一標識量。一般為去詳情的連接 currentPage:"data-page", //點擊當前的li的頁碼 pageResize:30, //與後臺交互的每頁返回的數量。 預設是30, goToDetailElement:$(".go-detail") , //滾動的每個列的總對象 nodeLi:"", //元素節點 getPageNum:"getPageNum", //1表示單頁數據,2表示雙頁數據。設置是請求單頁數據還是雙頁數據的標識量。放在URL上。 urlPageNum:"pageNum", //用於放到URL上面的參數標識表示當前是幾頁. pageNum = currentPage //返回來的時候用這個參數來判斷是不是需要滾動 }; var settings = $.extend(defaults,options || {}); dataPage = elements.attr(settings.currentPage); //求出點擊對象位於哪一個頁碼 logo = elements.attr(settings.logo); //求出當前對象的唯一標識量 containerHeight = parseInt(settings.container.outerHeight()); //容器的高度 scrollTopDistance = parseInt(settings.container.scrollTop()); //滾動的距離 elements.parent().find(""+ settings.nodeLi + "["+settings.currentPage + "=" + dataPage +"]").each(function(index, obj){ objLogo = $(obj).attr(settings.logo); elIndex = index; if(logo == objLogo){ prevNum = elements.prevAll().length; prevHeight = tool.getDistance(elements.parent().children(),prevNum - elIndex); prevCountPage = parseInt(prevNum / settings.pageResize); if(scrollTopDistance < prevHeight){ elements.parent().children().each(function(index,target){ if(prevCountPage > 0 ){ if(index < (prevCountPage - 1) * settings.pageResize){ prevCountPageDistance += parseInt($(target).outerHeight()); }; }; }); tool.changeUrlPar(settings.urlPageNum,dataPage - 1); //當前的頁數 tool.changeUrlPar(settings.getPageNum,2); //獲取雙頁數據 keepScrollTop = scrollTopDistance - prevCountPageDistance; //請求雙頁數據 向上 減 1; }else{ prevDistance = tool.getDistance(elements.parent().children(),(prevCountPage + 1) * settings.pageResize); prevPageScrollDistance = tool.getDistance(elements.parent().children(),prevCountPage * settings.pageResize); if(prevDistance < (scrollTopDistance + containerHeight)){ tool.changeUrlPar(settings.urlPageNum,dataPage); //點擊對象位於當前的頁數 tool.changeUrlPar(settings.getPageNum,2); //請求雙頁數據 keepScrollTop = scrollTopDistance - prevPageScrollDistance; }else{ tool.changeUrlPar(settings.urlPageNum,dataPage); //點擊對象位於當前的頁數 tool.changeUrlPar(settings.getPageNum,1); //請求單頁數據 keepScrollTop = scrollTopDistance - prevPageScrollDistance; }; }; }; }); tool.setSessionStorage("keepScrollTop",keepScrollTop); //保存滾動條的位置 return this; }; $.getSessionStorage = function(opt){ opt = sessionStorage.getItem(opt); return opt; }; })(window,jQuery,function(){ var tool = { changeUrlPar(arg, val){ //改變URL參數 function changeU(destiny, par, par_value) { var pattern = par+'=([^&]*)'; var replaceText = par+'='+par_value; if (destiny.match(pattern)) { var tmp = '/\\'+par+'=[^&]*/'; tmp = destiny.replace(eval(tmp), replaceText); return (tmp); } else { if (destiny.match('[\?]')) { return destiny+'&'+ replaceText; } else { return destiny+'?'+replaceText; } } return destiny+'\n'+par+'\n'+par_value; } var hash = window.location.hash; history.replaceState(null,'',location.pathname+location.search); url = window.location.href; var newUrl = changeU(url,arg,val) + hash; history.replaceState(null,'',newUrl); return false; }, removeUrlPar(options){ history.replaceState(null,'',location.pathname+location.search); var newParamStr = ""; var quotes = window.location.href.indexOf("?"); if(quotes != -1){ var webUrl = window.location.href.split("?")[0]; var paramsStr = window.location.href.split("?")[1].toString(); if(paramsStr.indexOf("&") != -1){ var pageIndex = paramsStr.indexOf(options); if(pageIndex != -1){ var pageArr = paramsStr.split("&"); for(var i = 0; i < pageArr.length; i++){ if(pageArr[i].match(options)){ pageArr.splice(i,1); }; }; newParamStr = pageArr.join("&"); }else{ newParamStr = paramsStr; } ; }else{ if(paramsStr.match(options)){ newParamStr = ""; }else { newParamStr = paramsStr; }; }; history.replaceState(null,'',webUrl + "?" + newParamStr); }else{ history.replaceState(null,'',w.location.href); } }, getDistance(obj,maxNum){ var h = 0; obj.each(function(index,target){ if(index < maxNum){ h += parseInt($(target).outerHeight()); } }); return h; }, setSessionStorage(keyName,opt){ sessionStorage.setItem(keyName,opt); console.log(opt) }, } return tool; }) $("li").on("click",function(){ $(this).savePosition({pageResize:15}); /* * 1.http://localhost/index.php/Home/Web?pageNum=2&getPageNum=1 * 點擊玩了以後url就變成這樣了。這時候表示 返回來的時候請求第二頁的數據。只請求一次。從第二頁開始 * * 2.http://localhost/index.php/Home/Web?pageNum=1&getPageNum=2 * 這樣表示請求也數據。從第一頁的數據開始 * */ var _herf = $(this).attr("data-url"); window.location.href = _herf; }); //當我們初始化的時候 var pageNum = 1,getPageNum = 2; //這兩個數的值是從URL中獲取的。只有從詳情返回來 時候,才有 if(!!pageNum && !!getPageNum){ //其中還有很多判定,肯定是先獲取數據在滾動。。。 $(window).scrollTop($.getSessionStorage('keepScrollTop')); }else{ } </script> </html>View Code
這個返回定位的插件基本就開發完畢了。當然對於實際的項目中,還有很多的改動。比如返回的時候,一定要把設置的標誌參數去掉。
4.本篇博文,全部原創。如有錯誤之處,歡迎指出。