之前一直沒有寫相關的作業心得筆記,一方面是覺得難度不高,一方面覺得操作幾次就很熟練了,所以就很懶惰…但進入到學期2-2後,光是S2的製作電影清單,突然感覺難度一下提升超級多,很多內容不是一次兩次就能夠記起來且熟悉,而且函式的拆解跟邏輯複雜度上也提升相當多,演算法也來到了百行之多,這時才發現真的很難一下吸收,所以決定開始來寫學習、作業、技術相關筆記來加深自己的記憶及熟練度。
任務
這次的任務是要把S2製作的My Movie List做進化,且要滿足以下幾個功能
- 要新增一組功能按鈕,可以將畫面呈現為列表模式及卡片模式。
- 畫面能夠順利在 list 和 card 模式間來回切換。
- 不能影響到原有功能(尤其是 More、收藏按鈕、分頁功能要正常運作)
Step 1:將按鈕樣式置入
第一步老樣子,先從HTML下手吧!先將Font Awesome按鈕的樣式置入頁面中,並且調整至適當的位置。
說明:
要先將Font Awesome的JS先置入head裏頭。之後在Font Awesome裡尋找相關icon的class碼,安排它在Html的位置,也要適時的調整Row或col(Boostrap開發模式),最後別忘了給他們的父層,以及各自都加上屬於自己的id。
Step 2:清單模式在畫面上呈現的樣子
只要先寫出一列的樣板模式即可,因為之後要用JS把設定好的HTML格式資料至入到畫面上。
Step 3:改造function
首先我們可以複製renderMovieList這個函式,並將它命名為renderMoviesList2之後方便做測試,基本上函式內的邏輯都一樣,只要將新寫的HTML格式資料帶到到rawHTML即可。所以去HTML把你剛剛寫好的格式放進rawHTML吧,記得要把電影名稱或相關要顯示的資料,替換成正確的參數。
之後可以將最下方renderMovieList改成renderMovieList2,來看看是不是正確顯示在螢幕上。
Step 4:新增監聽器
在Step 1置入icon的時候,就將自己和父層都設定好了id。
所以先回到上頭設定常數,將各自的位置選擇出來。
然後在父層掛上監聽器。
這邊我設定的父層為btnShowStyle
- 因為在按鈕上有設置a標籤,所以要先取消超連結本上的預設動作。
- 加入判斷式,確定是選擇到哪一個按鈕。
- 接著變更圖案本身的顏色樣式,因為是使用boostrap系統,所以要將各自的classList做新增或刪除。(使用狀態下為藍色primary,非使用狀態下為灰色secondary)
- 最後面的renderMovieList記得改成renderMovieList2
最後來檢查按鈕是否有成功,此時按下按鈕,按鈕要會變色,且會變換顯示的模式
Step 5:優化顯示模式的語法。
由於現在將兩個不同的顯示方式分成兩個函式來寫,會增加後面管理程式碼的困擾,因為只要碰到任何跟渲染畫面”renderMovieList”的時候,都要去判斷要用renderMovieList或是renderMovieList2,包含查找功能,換頁功能都有用到renderMovieList這個函式,為了不去更改原有的程式碼,所以決定把這兩個函式合併。
先將renderMovieList2內的程式碼先搬到renderMovieList後面,
接著就是加入判斷式,
這邊思考後,我的想法是先在最上頭新增一個變數 showStyle作為信號開關,
接著在renderMovieList加上判斷式,若showStyle等於0時,使用cards的顯示方式,否則就顯示清單模式。
接著回到顯示模式監聽器,加入當選則卡片時showStyle重新賦值為0,選擇清單時,showStyle重新賦值為1。
最後檢查一遍把確定所有的renderMovieList不要有出現之前寫的renderMovieList2。
現在頁面已經可以順利切換了,而且也優化了程式碼,未來若要新增第三種第四種顯示方式,只要在renderMovieList內新增新的判斷及格式,還有在樣式顯示監聽器內加入新的判斷就可以了。
目前原有的功能也要都能夠正常運作,只要選定一種顯示方式,不管用搜尋、換頁都會保持原有的顯示方式。
但是發現一個小問題,當我在卡片狀態下然後在第三頁時,當我按下變換樣式顯示頁面內容會回到第一頁,應該要顯示當頁才對。
這時候回頭檢視所有的renderMovieList帶入的引數發現,全部都帶入了getMoviesByPage(1),所以不管搜尋、換頁,只要碰到getMoviesByPage(1)帶入的是1時,全都會回到第一頁。
Step 6:修正所有的getMoviesByPage(1)
除了搜尋監聽器內的getMoviesByPage(1)。
回到最上方設定一個新的變數page 且賦予值 1。
再來將所有的getMoviesByPage的引數帶入page
getMoviesByPage(page)
這邊要注意,**除了搜尋監聽器內的getMoviesByPage(1)**,不能修改。
然後在回到之前頁碼生成的函式內,將原本的定義page為變數的let拿掉。
現在只要切換頁面就會給page重新賦值,page被確定下來,就算換樣式,也還是會保持在原本該顯示的頁數了。
除了搜尋監聽器內的getMoviesByPage(1)不能改原因
因為現在page在globle的狀態,假設一開始先切換到第三頁,page值此時會被賦予3,搜尋監聽器內的getMoviesByPage()引數如果是page的情況下’’renderMovieList(getMoviesByPage(page))’’,這時候搜尋任何關鍵字,搜尋結果是少於三頁的情況下,會發現此刻畫面會變一片空白沒有資料,那是因為我們變成渲染頁數變成第三頁,但是結果少於三頁,所以當然就沒有任何電影顯示出來。
所以再次強調
除了搜尋監聽器內的getMoviesByPage(1),不能修改。
除了搜尋監聽器內的getMoviesByPage(1),不能修改。
除了搜尋監聽器內的getMoviesByPage(1),不能修改。
已完成任務 (已完成的畫刪除線)要新增一組功能按鈕,可以將畫面呈現為列表模式及卡片模式。畫面能夠順利在 list 和 card 模式間來回切換。不能影響到原有功能(尤其是 More、收藏按鈕、分頁功能要正常運作)
由於程式碼篇幅頗長,請運用 description 欄位說明新增的功能,幫助助教能有效注意到重點。在程式碼中也請運用註解來提示助教!
已完成的視覺與使用者動線驗收重點 (已完成的畫刪除線)
切換顯示模式時,內容能停留在原本的頁面,不會跳回第一頁若使用搜尋後,再切換顯示模式,仍然能正常顯示搜尋結果- 視覺上能讓使用者知道現在選的是第幾頁、
哪個顯示模式、哪些項目有加入收藏
看來只剩下最後兩項了,加把勁!
Step 7:讓使用者知道現在位在第幾頁。
隨著改變頁數要改變頁碼的顯示樣式,這代表每當我選了一次頁碼,我勢必要重新渲染一次頁碼,所以表示一定會是從這兩個部分下手
- renderPaginator(在正確的頁數上改變樣式)
- Paginator的監聽器(換頁數就重新render)
我們先到Paginator監聽器來,這邊比較容易修改,我們只要在最後加上
新增data運算子,因為每次點選換頁按鈕都得重新渲染頁面按鈕,更新顯示正在哪一頁上,所以要看是依filteredMovies來重新渲染頁碼或是movies來重新渲染頁碼,如果搜尋情況下filteredMovies會有資料,將會依搜尋結果的情況下去產生頁碼,若否則會依照原本movies的資料長度去產生頁碼。
再來我們接著修改函式renderPaginator(在正確的頁數上改變樣式)
函式當中,一旦我們置入所有頁碼的HTML格式資料後,我們就可以立刻選取到各li子元素,而因為globle的page會被更新,此時便可以依照global的page去指出是哪一個li子元素裡的a元素標籤應該要被修改樣式。
paginator.children[0]為第一頁的li標籤
paginator.children[0].firstElementChild為li裡面的a標籤
paginator.children[0].firstElementChild.classList.add(‘bg-primary’, ‘text-white’)
a標籤新增名稱至class內(boostrap改變樣式)
最後再回到搜尋監聽器上,當搜尋為空白的時候,我們要顯示全部的電影,但別忘了要記得清空filteredMovies,因為filteredMovies現在已經移出到globle當中,也有很多函式都有使用到他,連續操作搜尋下,萬一filteredMovies保留之前的搜尋結果,將會出現顯示錯誤電影資料。
最後再補上一個執行產生頁碼函式。
這樣讓使用者知道現在選的是第幾頁就大功告成啦!
Step 8:顯示哪些項目有加入收藏。
這大概是所有題目內,我覺得最困擾的一個題目了,邏輯性比較複雜。
我思考的邏輯是,先製作一個新的function:
一開始先設定幾個常數:
- 選出所有class為card-title的元素(應該有12個,因為每頁顯示12筆),並放入panelMovies,之後就可以使用panelMovies[i].innerText來取得畫面上的電影名稱。
- 將我最愛的電影從locoalStorage取出並從JSON轉成Object,並放入favoriteMoviesList
- 將favoriteMoviesList使用map製造出一個新的陣列,條件是每一筆電影資料的電影名稱,並放入favoriteMoviesTitle
- 重複畫面上總共有幾部電影,就重複檢查多少次,for迴圈
加入判斷式,若favoriteMoviesTitle裡面含有畫面上第i部的電影名稱,修改”新增至我的最愛按鈕”的顯示樣式。
補充說明:
- 第140行,當選擇到元素標籤時,可以使用setAttribute(’string’,’value’)來設定新的標籤屬性,兩個引述都是字串,無屬性值的時候要輸入空字串。
- 對陣列使用map(),會將陣列中每一個項目,依照條件,產生一組新的陣列
Array.prototype.map() - JavaScript | MDN
The method creates a new array populated with the results of calling a provided function on every element in the calling array. callbackFn Function that is called for every element of arr. Each time callbackFn executes, the returned value is added to newArray.
Mozilla
大功告成,完成了所有作業要求了!
最後再檢查一遍作業的批改標準吧!
詳細的檢查一遍,操作看看,有沒有發現其他的小錯誤,若沒有大致上應該沒有問題啦!