萬盛學電腦網

 萬盛學電腦網 >> 腳本專題 >> javascript >> 超贊的動手創建JavaScript框架的詳細教程

超贊的動手創建JavaScript框架的詳細教程

   這篇文章主要介紹了動手創建JavaScript框架的詳細教程,包括DOM和各種屬性的調試等各個方面,超級推薦!需要的朋友可以參考下

  覺得Mootools不可思議?想知道Dojo是如何實現的?對JQuery的技巧感到好奇?在這篇教程裡,我們將探尋框架背後的秘密,然後試著自己動手建立一個你所喜愛的框架的簡易版本。

  我們幾乎每天都在使用各種各樣的JavaScript框架。當你剛入門的時候,方便的DOM(文檔對象模型)操作讓你覺得JQuery這樣的東西非常棒。這是因為:首先,對於新手來說DOM太難理解了;當然,對於一個API來說難以理解可不是什麼好事。其次,浏覽器間的兼容性問題非常令人困擾。

  我們將元素包裝成對象是因為我們想要能夠為對象添加方法。

  在這個教程裡,我們將試著從頭實現這些框架之一。是的,這會很有趣,不過在你太過興奮前我要澄清幾點:

  這不會是一個功能很完善的框架。的確,我們要寫很多東西,但它還算不上JQuery。可是我們將要做的事情會讓你體驗到在真正編寫框架的感覺。

  我們不打算保證全方位的兼容性。我們將要編寫的框架能夠在 Internet Explorer 8+、Firefox 5+、Opera 10+、Chrome和Safari上工作。

  我們的框架不會覆蓋到所有可能的功能。比如說,我們的append和preappend方法只有在你傳給它一個我們框架的實例時才能工作;我們不會用原生的DOM節點和節點列表。

  另外:盡管在教程中我們不會為我們的框架編寫測試用例,但是我已經在第一次開發它的時候做好了。你可以從 Github上獲取框架和測試用例的代碼。

  第一步: 創建框架模板

  我們將從一些包裝代碼開始,它將容納我們的整個框架。這是典型的立即函數(IIFE).

  ?

1 2 3 4 5 6 7 8 9 window.dome = (function () { function Dome (els) { } var dome = { get: function (selector) { } }; return dome; }());

  你可以看到,我們的框架叫做dome,因為它是一個基本的DOM框架。沒錯,基本(lame有“瘸子”、“不完整”的意思,dom加lame等於dome)的。

  我們已經有了一些東西。 首先,我們有了一個函數;它將成為構造框架的對象實例的構造函數;那些對象將會包含我們選擇和創建的元素。

  然後,我們有了一個dome對象,它就是我們的框架對象;你可以看到它最終作為函數的返回值返回給了函數調用者(譯注:賦值給了window.dome)。這裡還有一個空的get函數,我們將用它從頁面裡選取元素。那麼,我們來填充代碼吧。

  第二步: 獲取元素

  dome的get函數只有一個參數,但是它可以是很多東西。如果它一個string(字符串),我們將假定它是一個CSS(層疊樣式表)選擇器;不過我們也可能得到一個DOM節點或者DOM節點列表。

  ?

1 2 3 4 5 6 7 8 9 10 11 get: function (selector) { var els; if (typeof selector === "string") { els = document.querySelectorAll(selector); } else if (selector.length) { els = selector; } else { els = [selector]; } return new Dome(els); }

  我們用document.querySelectorAll來簡單的選擇元素:當然,這將限制我們的浏覽器兼容性,不過對於這種情況還是可以接受的。如果selector不是string類型,我們將檢查它的length屬性。如果存在,我們就知道我們得到的是一個節點列表;否則,就是一個單獨的元素,我們將它放到一個數組裡。這是因為我們要在下面向Dome傳遞一個數組。你可以看到,我們返回了一個新的Dome對象。讓我們回到Dome函數並且為它填充代碼。

  第三步: 創建Dome實例

  這是Dome函數:

  ?

1 2 3 4 5 6 function Dome (els) { for(var i = 0; i < els.length; i++ ) { this[i] = els[i]; } this.length = els.length; }

  我強烈建議你去深入研究一些你喜歡的框架

  這非常簡單:我們只是遍歷了els的所有元素,並且把它們存儲在一個以數字為索引的新對象裡。然後我們添加了一個length屬性。

  但是這有什麼意義呢?為什麼不直接返回元素?因為:我們將元素包裝成對象是因為我們想要能夠為對象添加方法;這些方法能夠讓我們遍歷這些元素。實際上這正是JQuery的解決方案的濃縮版。

  我們的Dome對象已經返回了,現在讓我們來為它的原型(prototype)添加一些方法。我會直接把那些方法寫在Dome函數下面。

  第四步:添加幾個實用工具

  要添加的第一批功能是些簡單的工具函數。由於Dome對象可能包含至少一個DOM元素,那麼我們需要在幾乎每一個方法裡面都遍歷所有元素;這樣,這些工具才會給力。

  我們從一個map函數開始:

  ?

1 2 3 4 5 6 7 Dome.prototype.map = function (callback) { var results = [], i = 0; for ( ; i < this.length; i++) { results.push(callback.call(this, this[i], i)); } return results; };

  當然,這個map函數有一個入參,一個回調函數。我們遍歷Dome對象所有元素,收集回調函數的返回值到結果集中。注意我們是怎樣調用回調函數的:

  ?

1 callback.call(this, this[i], i));

  通過這種方式,函數將在Dome實例的上下文中被調用,並且函數接收到兩個參數:當前元素和元素序號。

  我們也想要一個foreach函數。事實上這很簡單:

  ?

1 2 3 4 Dome.prototype.forEach(callback) { this.map(callback); return this; };

  由於map函數和foreach函數之間的不同僅僅是map需要返回些東西,我們可以僅僅將回調傳給this.map然後忽略返回的數組;代替返回的是,我們將返回this,來使我們的庫呈鏈式。foreach會被頻繁的調用,所以,注意當一個函數的回調被返回,事實上,返回的是Dome實例。例如,下面的方法事實上就返回了Dome實例:

  ?

1 2 3 4 5 6 7 Dome.prototype.someMethod1 = function (callback) { this.forEach(callback); return this; }; Dome.prototype.someMethod2 = function (callback) { return this.forEach(callback); };

  還有一個:mapOne。很容易就知道這個函數是做什麼的,但是真正的問題是,為什麼需要它?這就需要一些我們稱之為"庫哲學"的東西了。

  一個簡短的"哲學"闡釋

  首先,對於一個初學者來說,DOM很讓人糾結;它的API不完善。

  如果構建一個庫僅僅是寫代碼,那就不是什麼難事。但是當我開發這個庫時,我發現那些不完善的部分決定了一定數量的方法的實現方式。

  很快,我們要去構建一個返回被選擇元素的文本的text方法。如果Dome對象包含多個DOM節點(比如dome.get("li")),返回什麼?如果你就像jQuery那樣($("li").text())很簡單的編寫,你將得到一個字符串,這個字符串是所有元素的文本的直接拼接。有用嗎?我認為沒用,但是我不認為沒有更好的辦法。

  對於這個項目,我將以數組方式返回多個元素的文本,除非數組裡只有一個元素,那麼我僅僅返回一個文本字符串,而不是一個包含了一個元素的數組。我想你會經常去獲取單個元素的文本,所以我們優化了那種情況。但是,如果你想去獲取多個元素的文本,我們的返回你也會用著很爽。

  

copyright © 萬盛學電腦網 all rights reserved