價位公道,施工標準,告別房屋漏水 室內壁癌問題,防水工程規劃,來電免費勘漏 | 任何細節都不馬虎,提供大樓、辦公室清潔 外牆清洗專業評估,價格公道。歡迎來電洽詢 |
[JQuery] 自製 jQuery Plugin |
房東:小凱 發表時間:2011-05-06 |
有時候寫 jQuery 時,常會發現一些簡單的效果可以重複利用。只是每次用 Copy & Paste 大法似乎不是件好事,有沒有什麼方法可以讓我們把這些效果用到其他地方呢? 沒錯,就是用 jQuery 的 Plugin 機制。 不過 jQuery 的 Plugin 機制好像很難懂?其實一點也不。以下我用最簡單的方式來為大家解說如何自製一個簡單的 Plugin 。 當然在此之前,你得先瞭解 JavaScript 的 class 、 object 、 variables scope 還有 anonymous function 等基礎,這些可以參考「 JavaScript 大全」一書。
Plugin 樣版寫 jQuery 的 Plugin 最快的方法就是拿現成的 Plugin 來改,只是在那麼多的 Plugin 中怎麼找到好的範例呢?別擔心,這邊我提供一個最簡單的範例樣版: jQuery.fn.mytoolbox = function() { 首先, mytoolbox 就是我們的 plugin 名稱,利用 jQuery.fn 我們可以將它註冊為 jQuery 的 plugin 。然後我們把 jQuery.fn.mytoolbox 指向一個匿名函式 (anonymous function) ,又稱為 callback ;而這個 callback 的內容很簡單,就是利用 jQuery 的 each 方法,來一一執行對應的動作。 特別要注意匿名函式裡的 this 關鍵字,它會指向一個 jQuery 物件;而這個 jQuery 物件則是我們要指定的,稍後我會再進一步說明。 使用 Plugin現在將上面的樣版存成 mytoolbox.js ,和 jquery.js 放在一起。然後建立一個 HTML 測試檔案,內容如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 首先 HTML 中引用了 jQuery 函式庫及我們寫的 Plugin 檔案,然後我在畫面上佈置了兩個 class 為 test 的 div 元素。接著我們用以下程式碼來呼叫我們的 Plugin : $(function () { 這邊的用意就是將上面那兩個 div 套上 mytoolbox 這個 Plugin ,這樣 Plugin 就能動了,很簡單吧? 加入動作當然,這個 Plugin 什麼事都還沒開始做,是個空骨架而已。現在我們要為它加血添肉,讓它動起來。 先簡單在 each 的 callback 裡加入一行: jQuery.fn.mytoolbox = function() { 再重新瀏覽測試用的 HTML 檔,你會發現頁面自動跳出了兩次訊息視窗,內容分別是 test1 和 test2 ;這證明了我們的 Plugin 的確有套用在 class 為 test 的兩個 div 上面。 不過現在有兩個 this ,它們是一樣的東西嗎?不,因為 scope 及觸發對象的不同,它們兩個是不同的東西。在外面的 this 是一個 jQuery 物件,指向我們指定的 $(‘.test’) 這個物件;而 each callback 裡的 this 則是 div 元素,因為 each 是個 iterator function ,因此 alert(this.id) 會執行兩次。在第一次的 this 會指向 #test1 這個 div ,第二次則指向 #test2 這個 div 。 註:這裡我用 #test1 表示 id 為 test1 的元素。 現在我希望改成按下 div 元素後才會 alert 該元素的 id ,這要怎麼做呢?我們要改用 click 事件,做法如下: jQuery.fn.mytoolbox = function() { 由於 each callback 裡的 this 是 DOM 元素,所以我們要用 jQuery() 把 this 包起來,這樣才能方便指定該元素的 click 事件。現在重新瀏覽頁面,點選任何一個 div ,應該就會跳出對應的訊息視窗了。 再包一層如果在 each 的 callback 裡會呼叫到多次的 jQuery 的話,一直寫 jQuery 這幾個字實在是很累人的一件事;而且 jQuery 不是可以簡寫成 $ 號嗎?不能直接用嗎?當然可以,只是這樣可能會和其他 JavaScript Library 發生衝突;所以我們要改用以下的方式來包覆我們的 Plugin : ;(function($) { JavaScript 可以直接用一組小括號 [()] 包覆一個匿名函式,然後後面再接一組小括號 [()] 表示呼叫這個匿名函式;而第二組小括號中就可以放置這個匿名函式的參數。所以在上面的程式碼中,我們把 Plugin 的程式碼用一個匿名函式包覆起來,然後參數就用我們常用的 $ 符號;接著在利用前述的原理,將 jQuery 這個類別導入給我們的 Plugin ,這樣我們就可以很快樂地在 Plugin 中使用我們熟悉的 $ 符號了。至於最前面的分號 (;) ,主要是考慮這個 Plugin 檔案會和其他 JS 檔合併壓縮而放進來的。 註: $ 在 JavaScript 裡是合法的變數名稱。 後面的說明我會略過這個包覆動作,在實際檔案中請別忘了加。 加入選項設定接下來我希望讓 each 的 callback 函式能讓使用者自訂,因此我需要一個讓使用者能設定的選項。就像其他的 Plugin 一樣,我們讓我們的 mytoolbox 可以接受一個 settings 物件: $.fn.mytoolbox = function(settings) { 首先我們為 Plugin 加入 settings 參數,也就是一般 Plugin 常見的設定值。然後則是 _defaultSettings ,它能幫我們在使用者沒有指定任何設定值給 settings 時,還能夠提供預設的設定值。 接著我用 jQuery 提供的 extend 方法,將 settings 中有設定的值覆蓋掉 _defaultSettings 所設定的預設值,再把結果存放在 _settings 這個變數中;後面我們就會用新的 _settings 變數當做我們的設定值。 現在我們在 _settings 中指定了一個 callback 項目 (預設是用 alert ) ,然後將它指定給 div 元素的 click 觸發器。現在我要在 HTML 頁面中更改這個事件處理器,使它不再使用 alert ,而是把結果顯示在 div#debug 裡。程式如下: $(function () { 再重新瀏覽一次頁面,看看效果是不是依照我們想像的完成呢? 修改觸發事件假設現在我們不想用 click ,而是想讓滑鼠移過就觸發 callback 呢?這時就要借重 jQuery 的 bind 方法了: $.fn.mytoolbox = function(settings) { 這裡我加入一個 bind 設定項目,預設是用 click 事件觸發。回到 HTML 頁面,我們改用 mouseover 來觸發 callback : $(function () { 重新瀏覽 HTML 頁面,當滑鼠移過 div 元素時,是不是會出現對應的 id 呢? 到這裡,相信大家都應該大致瞭解如何建立一個 jQuery Plugin 了吧?接下來,我將透過實際的例子為大家介紹更多自製 jQuery Plugin 所需要注意的地方。 |
|
廣利不動產-板橋在地生根最實在--新板特區指名度最高、值得您信賴的好房仲 完整房訊,房屋、店面熱門精選物件,廣利不動產 優質仲介,房屋租賃、買賣資訊透明,交易真安心! 廣利不動產-新板特區指名度最高、值得您信賴的好房仲 您的托付,廣利用心為您服務 |
1 樓住戶:小凱 發表時間:2011-05-06 |
在 Part 1 我們看到如何建立一個 jQuery Plugin 的雛形,也讓它能夠做一些簡單的動作了。只是這個 Plugin 似乎沒什麼太大的用途,所以接下來我們就來寫個真正能用的東西。
簡單的頁籤功能要舉個簡單又實用的教學用例子,一直都是非常困難的事情。經過多次的思考與挑選,我決定用頁籤功能 (Tab) 來當做本文練習的重點。 當然 jQuery 已經有一些 Tab 相關的 Plugin 了,而且基於不重造輪子的理念下,我們似乎不應該自己動手;不過站在學習的角度下,如果我們自己實作一個簡單的頁籤的話,將會有助於瞭解 jQuery Plugin 的設計過程。 以下先來瞭解我們需要的功能,再來想想看怎麼實作它。 首先我們的頁籤大概會長成這樣子: 基本上我們要的效果就是在點選上面的 TAB1 、 TAB2 及 TAB3 時,底下的文字區塊會跟著切換,這就是最簡單的頁籤功能了。 頁面結構在 HTML 的部份也非常簡單,基本上是一個 UL 清單 (div.tabs ul) 加上三個 DIV 區塊 (div.tabBlock) ,最後再用一個大 DIV 區塊 (div#mytab) 把它們包起來。 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 當然別忘了把 JavaScript 檔案引入,這裡我先把 mytoolbox.js 改為 mytab.js ,因為我們要做的是頁籤。 而頁籤樣式的部份則以是 CSS 來完成,請把它存檔並命名為 mytab.css : div.tabBlock { 這裡我們就不深究 CSS 怎麼做的了,有興趣的朋友請自行參考相關書籍。 準備 Plugin 樣版現在把 Part 1 的 mytoolbox.js 複製為 mytab.js ,然後稍做修改,如下: ;(function($) { 從上面的程式中可以看到我把 _defaultSettings 的內容清掉了,因為我們暫時用不到特別的設定。然後我把給 each 方法用的 callback 獨立為 _handler 函式,因為後面我們要做的動作大部份都會在這裡發生。 呈現頁籤下的區塊在套上 CSS 後,我們會看到三個 div.tabBlock 區塊同時都顯示出來了,這樣做的目的其實是為了當瀏覽器沒有開 JavaScript 時還能呈現資訊。而在開啟了 JavaScript 後,我希望只呈現第一個 div.tabBlock 區塊,這時我們就可以利用 jQuery 來完成: var _handler = function() { 在解釋原理之前,先回頭看一下 HTML 頁面呼叫 Plugin 的地方,你會發現我把 Plugin 套用在 div#mytab 這個元素上,所以在 _handler 裡的 this 其實是指向 div#mytab 。 瞭解 this 代表的意義後,接著回到 _handler 中,我們就可以知道第一行的 $(‘div.tabBlock’, this) 其實就是指抓取 div#mytab 底下的三個 div.tabBlock 元素。所以第一行我們先把所有的 div.tabBlock 隱藏起來,然後利用 .eq(0).show() 把第一個 div.tabBlock 顯示出來。 讓頁籤動起來接著我們先讓頁籤在點選時能夠切換它的反白狀態,而反白的效果我們已經定義 CSS 裡了,也就是讓 LI 的 class 變成 active 即可: var _handler = function() { 這邊的原理也很簡單,首先先讓所有 div.tabs li 都移除反白效果,然後再對我們按的連結的上一層 LI 元素套上 active 。注意這裡也有個 this ,它代表的是目前點選的頁籤連結。 最後我們要 return false ,以阻止 click 事件被往上傳遞。 現在點選看看頁籤連結,是不是能反白了呢? 註:滑過頁籤會呈現反白這個效果也是定義在 CSS 裡,試著找找看吧。 記住「這個」在繼續完成效果前,有個問題我得先說明一下。雖然我們在測試頁面上只佈置了一個 Tab 元件,不過很難保證頁面上不會有其他地方也會用到頁籤效果,這時我們的 Plugin 可能會產生副作用。 問題出在 $(‘div.tabs li’).removeClass(‘active’) 這行,因為我們不能確定頁面其他地方是不是也有有元素符合 $(‘div.tabs li’) 。所以我在這裡應該要明確指定這些 LI 元素應該屬於那個元素,也就是 $(‘div.tabs li a’, this) 的 this (即 div#mytab ) 。 不過在 click 方法指定的匿名函式中, this 又指到 a 元素,而不是我們要的 div#mytab ;那麼有什麼方法能在 click 中找到 div#mytab 呢?總不能把 div#mytab 寫死在 Selector 中吧?其實方法很簡單,就是在 click 外先定義一個新變數指向外部的 this : var _handler = function() { 因為在 click 的匿名函式會繼承外部的作用域,使得 container 的 scope 得以存在於 click 的 callback 裡;因此我們就能放心的使用 container 來表示 div#mytab 了。 註:在 click 裡的 callback 又有另一個名稱: closure ,因為它用到了外部 function 所定義的變數。 切換對應的區塊接著繼續完成我們要的功能,也就是切換頁籤對應的區塊。 這裡我用了連結錨點的技巧,這個技巧本身有個優點:就是當 JavaScript 被禁用時,錨點還能正常動作。而錨點的名稱剛好就是頁籤所對應的內容區塊 ID ,這就方便我們找到要顯示的內容區塊。 程式碼如下: var _handler = function() { 原理一樣很簡單,當按下頁籤連結時,先隱藏所有內容區塊 (div.tabBlock) ,然後取得連結的 href 位址中的錨點名稱,以顯示頁籤所對應的內容區塊。不過這裡要注意一點,那就是瀏覽器通常會幫我們在錨點名稱前加入目前完整的網址;因此我這裡便使用正規式來取得帶井字號的錨點名稱,也剛好直接讓 jQuery 使用。 減少多餘的查詢再看一次程式,我發現有個地方重複查詢了兩次,那就是 $(‘div.tabBlock’, container) ;第一次是在我們只顯示第一個內容區塊時,而第二次則在點選連結時要隱藏所有內容區塊時。這裡我們可以利用暫存變數來解決: var _handler = function() { 不過也不是每個重複的查詢都要用暫存變數,因為假設當你在 Plugin 運作的過程中,對 div.tabBlock 有進行增減的話,那麼重複再查一次就是必要的動作了,這樣才能確保我們抓到正確數量的元素集。 到這裡我們的 mytab.js 初版算是完成了,試試看它是不是依照我們的要求正確動作呢? 加強 Plugin雖然我們的 Plugin 已經可以動作了,但其實還是有些地方可以加強;而加入這些功能其實就是為了讓 Plugin 能更有彈性,以應付各種不同的狀況。 這裡我簡單介紹兩個加強的功能: 由外部決定 class我們希望可以指定 active 的名稱,讓外部可以自行決定。我們在 _defaultSettings 中多定義了一個 activeClass 項目,然後把程式裡的所有 ‘active’ 改為 _settings.activeClass 。程式碼修改如下: $.fn.mytab = function(settings) { 同樣的原理,我們可以更改 div.tabs 和 div.tabBlock 的 class 名稱,這邊我留給各位自行試試。 自動切換內容區塊現在我希望進入頁面時,能讓內容區塊自動跳到我指定的頁籤。這裡我有兩種方式可以指定:由網址決定以及用 Server 程式決定。 以網址決定就是我們在瀏覽器的網址列的網址後面再加上錨點名稱,例如: http://localhost/mytab.htm#tab2 這個網址可以由外部的網頁以連結的方式指定,這樣的話進入我們這個頁籤畫面時,我們就可以依照這個錨點來決定要顯示的內容區塊。程式很簡單: var _handler = function() { 原理就是透過錨點來顯示對應的內容區塊,再跟著把對應頁籤連結反白即可;如果沒有指定錨點的話,就顯示第一個內容區塊。 當然別忘了重構,把多餘的查詢動作用暫存變數取代: var _handler = function() { 回到主題,我們的另外一種指定內容區塊的方式就是在 Server 端輸出 HTML 時,就先決定好 active 的 LI 元素了。假設現在頁籤部份的 HTML 如下: <div class="tabs"> 現在 TAB2 這個 LI 元素的 class 是 active ,那麼我們應該怎麼自動切換到對應的內容區塊呢?很簡單,就讓 li.active 底下的 a 「點下去」就可以了。程式如下: var _handler = function() { |
姓名: | |||
佈告內容: | |||
其他選項: | |||
|