一,開篇分析html
Hi,你們好!大熊君又和你們見面了,還記得昨天的那篇文章嗎------這個系列的開篇(第一季)。主要講述了以「jQuery的方式如何開發插件」,json
那麼今天咱們帶着昨天的疑問來繼續咱們的插件開發之旅。昨天的問題以下:閉包
(1),若是項目技術選型換了這些插件又是強依賴「jQuery」機制,咱們之前寫的插件將會不能用(假設不用jQuery的狀況),如何作重構那?異步
(2),重構插件的關鍵邏輯,咱們將如何組織那?ide
好了,帶着問題去學習今天的文章吧。函數
首先我不是否認「jQuery插件的方式」,其次是咱們要從不一樣的角度分析問題,好比說「jQuery插件有以下優勢」:學習
(1),把所有代碼放在閉包(一個即時執行函數)裏此時閉包至關於一個私有做用域,外部沒法訪問到內部的信息,而且不會存在全局變量的污染狀況。測試
(2),a) 避免全局依賴;b) 避免第三方破壞;c) 兼容jQuery操做符'$'和'jQuery '。this
那咱們重構將以什麼方式組織代碼那,是面向對象的思想(OOP)那?仍是過程化的思路進行到底那?仍是二者結合設計那?哈哈哈,繼續看。。。。。。url
二,重構昨天的例子
如下是昨天的Js部分源碼部分:
1 (function($){ 2 $.fn.bigbear = function(opts){ 3 opts = $.extend({},$.fn.bigbear.defaults,opts) ; 4 return this.each(function(){ 5 var elem = $(this) ; 6 elem.find("span").text(opts["title"]) ; 7 $.get(opts["url"],function(data){ 8 elem.find("div").text(data["text"]) ; 9 }) ; 10 }) ; 11 } ; 12 $.fn.bigbear.defaults = { 13 title : "這是一個簡單的測試" , 14 url : "data.json" 15 } ; 16 })(jQuery) ;
咱們來逐行分析一下:
首先肯定一下這個插件的功能
(1),顯示咱們設置的標題文字信息。
(2),動態經過異步的方式獲取內容信息。
好了!需求明確就好展開討論了,從上面的代碼不難看出邏輯組織很鬆散,過程化的思惟很明顯,因此第一步就是把咱們的功能需求
以類的方式有效地組織起來。看以下重構後的代碼:
1 $(function(){ 2 $("#bb").bigbear() ; 3 }) ; 4 (function($){ 5 $.fn.bigbear = function(opts){ 6 opts = $.extend({},$.fn.bigbear.defaults,opts) ; 7 return this.each(function(){ 8 var elem = $(this) ; 9 var bb = new BigBear(elem,opts) ; 10 bb.getElem().trigger("data") ; 11 }) ; 12 } ; 13 $.fn.bigbear.defaults = { 14 title : "這是一個簡單的測試" , 15 url : "data.json" 16 } ; 17 })(jQuery) ; 18 19 function BigBear(elem,opts){ 20 this.elem = elem ; 21 this.opts = opts ; 22 this.init() ; 23 } ; 24 var bbProto = BigBear.prototype ; 25 bbProto.getElem = function(){ 26 return this.elem ; 27 } ; 28 bbProto.getOpts = function(){ 29 return this.opts ; 30 } ; 31 bbProto.init = function(){ 32 var that = this ; 33 this.getElem().on("data",function(){ 34 that._setTitle(that.getOpts()["title"]) ; 35 $.get(that.getOpts()["url"],function(result){ 36 that.getElem().find("div").text(result["text"]) ; 37 }) ; 38 }) ; 39 } ; 40 bbProto._setTitle = function(text){ 41 this.getElem().find("span").text(text) ; 42 } ;
哈哈哈,是否是代碼多了很多,其實這種方式就是面向對象的角度看問題,先去分析功能需求,而後設計咱們的類,雖說咱們不可能一下設計得很出色,
可是看問題角度改變了,咱們的代碼可讀性強了,以及更好地進行維護這樣咱們的目的也就達到了。
如下是是摘自「Bootstrap」Js部分的相關源碼實現,以下圖:
不難看出也是類似的實現方式,經過類來維護咱們插件的主要邏輯。
(三),增長新功能,引出額外的類
如今需求增長了,須要在體驗上有所變化,加載數據時有「loading」效果。
實現思路能夠這樣,在原始的內容區把文字設置成「裝載數據中。。。。」的字樣,而後引入一個新的類,以下:
1 function Overlay(){ 2 3 } ; 4 var olProto = Overlay.prototype ; 5 olProto.show = function(){} ; 6 olProto.hide = function(){} ; 7 // 具體實現就不寫了
好了,遮罩層已經有了,如今咱們怎麼集成進來那?咱們用組合的方式接入進來,以下:
1 function BigBear(elem,opts){ 2 this.elem = elem ; 3 this.opts = opts ; 4 this.overlay = new Overlay() ; 5 this.init() ; 6 } ; 7 var bbProto = BigBear.prototype ; 8 bbProto.getElem = function(){ 9 return this.elem ; 10 } ; 11 bbProto.getOpts = function(){ 12 return this.opts ; 13 } ; 14 bbProto.init = function(){ 15 var that = this ; 16 var loadingText = "數據裝載中。。。" ; 17 this.getElem().on("data",function(){ 18 that._setTitle(that.getOpts()["title"]) ; 19 that.overlay.show() ; 20 that.getElem().find("div").text(loadingText) ; 21 $.get(that.getOpts()["url"],function(result){ 22 that.overlay.hide() ; 23 that.getElem().find("div").text(result["text"]) ; 24 }) ; 25 }) ; 26 } ; 27 bbProto._setTitle = function(text){ 28 this.getElem().find("span").text(text) ; 29 } ;
到此只爲咱們的功能就算是結束了,這樣寫的插件,我相信比第一個版本好不少,固然這不是最優的實現,須要從細節上不斷重構,可是這種方式是一種可選的開發插件的方式。
如下是完整的代碼:
1 $(function(){ 2 $("#bb").bigbear() ; 3 }) ; 4 (function($){ 5 $.fn.bigbear = function(opts){ 6 opts = $.extend({},$.fn.bigbear.defaults,opts) ; 7 return this.each(function(){ 8 var elem = $(this) ; 9 var bb = new BigBear(elem,opts) ; 10 bb.getElem().trigger("data") ; 11 }) ; 12 } ; 13 $.fn.bigbear.defaults = { 14 title : "這是一個簡單的測試" , 15 url : "data.json" 16 } ; 17 })(jQuery) ; 18 19 function BigBear(elem,opts){ 20 this.elem = elem ; 21 this.opts = opts ; 22 this.overlay = new Overlay() ; 23 this.init() ; 24 } ; 25 var bbProto = BigBear.prototype ; 26 bbProto.getElem = function(){ 27 return this.elem ; 28 } ; 29 bbProto.getOpts = function(){ 30 return this.opts ; 31 } ; 32 bbProto.init = function(){ 33 var that = this ; 34 var loadingText = "數據裝載中。。。" ; 35 this.getElem().on("data",function(){ 36 that._setTitle(that.getOpts()["title"]) ; 37 that.overlay.show() ; 38 that.getElem().find("div").text(loadingText) ; 39 $.get(that.getOpts()["url"],function(result){ 40 that.overlay.hide() ; 41 that.getElem().find("div").text(result["text"]) ; 42 }) ; 43 }) ; 44 } ; 45 bbProto._setTitle = function(text){ 46 this.getElem().find("span").text(text) ; 47 } ; 48 49 function Overlay(){ 50 51 } ; 52 var olProto = Overlay.prototype ; 53 olProto.show = function(){} ; 54 olProto.hide = function(){} ; 55 // 具體實現就不寫了
(四),最後總結
(1),面向對象的思考方式合理分析功能需求。
(2),以類的方式來組織咱們的插件邏輯。
(3),不斷重構上面的實例,最好本身寫一下,而且完善「Overlay」的邏輯。
(4),你們學習完繼續思考一下,如何進行合理的重構那?不要設計過分,要遊刃有餘,推薦的方式是過程化設計與面向對象思想設計相結合。
哈哈哈,本篇結束,未完待續,但願和你們多多交流夠溝通,共同進步。。。。。。呼呼呼……(*^__^*)