3.8_圖片輪撥Slider_物件導向
運用prototype屬性,達成物件導向的繼承功能。 重構圖片輪撥的slider功能,使其程式結構更完整。
- js結構化寫法
- js的資料型態-function等於object
- prototype屬性介紹
- 類別產生實例(instance)之後,this的不同
- 類別產生多個實例(instance)之後,重覆的屬性和方法(method)
- 運用prototype屬性,在父層宣告方法
- 傳送html物件給類別-Slider,來設定屬性和方法
- 點選按鈕,移動圖片
- current變數遞增遞減,控制圖片前後移動
- 修正位移第一張和最後一張圖片的current判斷式
- 完成結構化的Slider外掛
js結構化寫法
上一章中,我們已經完成了slider來捲動圖片的功能,這一章我們我使其寫法更加結構化,以便讓日後的程式碼更易擴充新功能
介紹javascript的prototype的一個學習網站->scriptjunkie
另 一個為Modulus的學習網站
js的資料型態-function等於object
我們至今都已有一些寫javascript的經驗了,我們都很熟悉於宣告一個陣列,如:var arr=[1,2,3],而如要新增一個陣列物件可用其push()的方法。但是當你使用push()的時後,你有沒有想過,這個push()是怎樣來的?javascript並沒有class(類別物件),那樣如何建立此方法psuh()?
因此,javasctip一定有其它的型態可達成class(類別)的功能,我們開始逐漸偵測各種變數的型態。首先,先測試Array的態態,輸入dir(Array)來判斷其型態為何,結果Array的型態為function
也可用typeof的方式測試變數型態,一樣測出來為function
這次換測試Object的型態,結果也一樣是function
function竟然包含了屬性和方法!這代表了在javascript中的function型態,等同於其它程式語言的class
prototype屬性介紹
解說因為prototype屬性的原因,任何由Array所產生的物件(如:arr = new Array()),都可使用包含在ptototype的方法,但是只有呼叫new array()產生實例時,才能被使用,才會佔用到記憶體
類別產生實例(instance)之後,this的不同
尚未產生新的實例(instance)以前,this代表為window
new Slider();//用來產生slider實例
運行結果,console出Slider物件內的this為Slider//產生實例後this就不再是window了
類別產生多個實例(instance)之後,重覆的屬性和方法(method)
在此Slider物件內,新增自訂的屬性direction和方法move(),並透過Slider.move()來執行
運行結果,成功執行自訂的方法,console出moving字串
產生2個Slider()的實例,slider和slider2,並用console.dir()觀察其內部的變數
運行結果,可看到2個實例化的slider,都擁有各自獨立的屬性和方法。但我們不需要複製出這麼多的方法(move()只要一個就夠了,沒必要個自獨立為一個)。所以要如何利用物件導向的方法,來做到在其父層宣告方法後,在讓子層去繼承就好了呢?
運用prototype屬性,在父層宣告方法
使用prototype的屬性,讓move()宣告在父層,以便之後其子層可直接繼承。
運行結果,可看到_proto_的物件內新增了move()的方法,這樣的寫法就不會產生重覆的move()了
可看到所產生的2個實例都可使用move()的方法。那是因為使用prototype在父層宣告方法後,子層繼承了父層的原因
運行結果,可看到2個slider和slider2的實例,都執行了move(),輸出字串moving
direction變數是宣告在slider物件內,而非prototype內。因此在各別實例化後,direction變數便會各自獨立(輸入forward和backward,這2個參數是各自獨立的)
運行結果,分別測出2個direction變數分別為forward和backward
強調在prototype宣告的方法(父層),仍可使用在子層宣告的變數direction
運行結果,成功合用位於父層的方法move(),和子層的變數direction來完成javascript內物件導向的基本應用
再次建議大家如要了解javascript物件導向的繼承概念,請看網站scriptjunkie的教學-
傳送html物件給類別-Slider,來設定屬性和方法
學會了基礎的繼承概念後,接下來我們開始一步步的將上一課程的Slider圖片捲動的功能,轉為更具結構的寫法。
首先,建立一個類別Slider,並將$('div.slider'),傳入此類別來供後續動作
先確定html的物件<div class="slider"></div>,有傳入Slider類別內了
function Slider(container,nav)//接收容納圖片的div.slider做為container參數,和放置按鈕的#slider-nav為nav參數,來加以設定Slider的屬性和方法。
Slider.prototype.transition//運算圖片的徧移位置
點選按鈕,移動圖片
slider.transition(-1800)//圖片移動間距設為-1800
運行結果,沒看到圖片?!因為移動了錯誤的div,包含圖片的div為$('div.slider ul')而非$('div.slider')
將Slider傳入的參數改為$('div.slider ul')
運行結果,正確位移-1800側image4的位置
依此類推,位移0為image1,-600為image2,-1200為image3
Slider.transition();//如果沒有輸入任何位移的數值,預計是會依序移動的
運行結果,點選Next按鈕,此功能尚未成功運作,因為尚未寫入current數值變動,來達到圖片移動的功能。
current變數遞增遞減,控制圖片前後移動
透過判斷點選按鈕所傳入的dir參數是否為'next',來決定current要遞增或是遞減。
使用xx?xx:xx的判斷式為if else的簡寫法,你可自行選擇判斷式的寫法。
在console中解說~~的功能//boolean值轉數字,true轉為1,false轉為0。
(div === 'next')//為true,經~~轉為數值1
(div === 'prev')//為false,經~~轉為數值0
dir等於'next'時,this.current遞增1,否則遞增-1
運行結果,console檢測,點按next數值遞1, 點按prev遞減1
但減過頭會有負值產生喔,所以需修改判斷式
修正位移第一張和最後一張圖片的current判斷式
pos小於0時,就跳至圖片的最後一張
運行結果,在第一張img時,點選prev,console出this.current為3(已成功完成從第一張跳至最後一張的判斷式)
在console中解說%符號的功能
2%4 (2除以4,餘數為2)
1%4(1除以4,餘數為1)
4%4 (4除以4,餘數為0),根據此特性,第一張圖時,pos為0
pos(目前的圖片)%this.imgsLen(全部圖片數)
//第一張圖時,current為0,按next,(0+1)%4=1
//第二張圖時,current為1,按next,(1+1)%4=2
//第三張圖時,current為2,按next,(2+1)%4=3
//第四張圖時,current為3,按next,(3+1)%4=0(就會跳回第一張了)
作者使用skitch plus(手寫繪圖工具),來說曘%運算餘數的概念
6%4=2
完成結構化的Slider外掛
改名為setCurrent並回傳運算後的pos值
運用已完成的setCurrent的方法,來傳入移動方向的參數,來運到圖片前後移動的效果
運行結果,成功達成點按prev圖片跳至前一個,點按next圖片圖片跳至下一個的效果
但是圖片捲動的scrollbar還沒有隱藏
那是因為目前的css檔中,.slider{overflow:scroll;}//需設定為hiddeen才能將scrollbar隱藏
$('div.slider').css('overflow', 'hidden')//只有javascript有運作的瀏灠器才需將scrollbar設為hidden,關閉javascript的使用者,還是需要保留scrollbar,才留移動圖片。
新增的container變數,取代原先的$('div.slider ul')傳給new Slider()。
Slider.nav.show()改成slider.nav,因要將控制是否要顯示的部份傳到獨立的slider.js來進行控制。
this.nav = nav.show();//由傳入的nav參數來控制顯示
運行結果,scrollbar消失了,且功能正常運行
把javascript先刪掉,看看無js時,只有css的功能是否正常
運行結果,沒有js時,按鈕成功隱藏,只讓使用者透過scrollbar移動圖片的功能正常運行。
結論,成功完成結構化的slider外掛。