2021-07-29|閱讀時間 ‧ 約 15 分鐘

預讀學期2-2,S3,A12:電影清單加碼功能 作業心得

之前一直沒有寫相關的作業心得筆記,一方面是覺得很難度不高,一方面覺得操作幾次就很熟練了,所以就很懶惰...但進入到學期2-2後,光是S2的製作電影清單,突然感覺難度一下提升超級多,很多內容不是一次兩次就能夠記起來且熟悉,而且函式的拆解跟邏輯複雜度上也提升相當多,演算法也來到了百行之多,這時才發現真的很難一下吸收,所以決定開始來寫學習、作業、技術相關筆記來加深自己的記憶及熟練度。

任務

這次的任務是要把S2製作的My Movie List做進化,且要滿足以下幾個功能
  1. 要新增一組功能按鈕,可以將畫面呈現為列表模式及卡片模式。
  2. 畫面能夠順利在 list 和 card 模式間來回切換。
  3. 不能影響到原有功能(尤其是 More、收藏按鈕、分頁功能要正常運作)
  4. 由於程式碼篇幅頗長,請運用 description 欄位說明新增的功能,幫助助教能有效注意到重點。在程式碼中也請運用註解來提示助教!

驗收重點

驗收重點現階段期待你做到⋯⋯開發框架/函式庫(略)程式邏輯與 Coding Style以你目前的程度,我們期待你在「成功做出功能」以後,認真地花點時間優化程式碼品質,強化邏輯清晰度、提高可讀性、減少重複,畢竟我們的程式碼體量愈來愈大了,以下我們列出可能的方向,請你這次務必要「一邊實作一邊刻意優化」:
  • 程式邏輯是否清晰
  • 每個函式都有明確的職責,一個函式專心做一件事,例如例如 card 模式渲染、 list 模式渲染、判定模式等
  • 避免不必要的變數
  • 減少暴露在 global 區域的程式碼,也就是說,若你在這份作業中新增了功能,這些功能的程式碼必須被封裝在函式裡。
  • 宣告變數時需注意
  • 使用 let & const 宣告變數 (不要使用 var)
  • 不會變動的內容用 const,要變動的內容才用 let
  • 清晰易懂的變數命名
  • 變數用名詞、函式用動詞、陣列使用複數型
  • 名稱與內涵盡力一致 (不要嫌單字太多、講清楚最重要)
  • 新增顯示模式的切換功能後,原有的搜尋功能仍能正常運作 (如:按下 search 能啟動搜尋、執行新的搜尋時,有先清空頁面再呈現搜尋結果)
  • 變數資料型態保持前後一致
  • 命名是否有意義、可讀性
  • 適當運用註解幫助他人快速理解程式碼
  • 盡量避免多餘的程式碼 - 尤其是測試過程中的 console.log
  • 遵守 JavaScript Standard style (建議安裝自動檢查套件)
視覺與使用者動線
  • 切換顯示模式時,內容能停留在原本的頁面,不會跳回第一頁
  • 若使用搜尋後,再切換顯示模式,仍然能正常顯示搜尋結果
  • 視覺上能讓使用者知道現在選的是第幾頁、哪個顯示模式、哪些項目有加入收藏

行有餘力:優化品質、擴充規格

除了上面的 coding style 驗收重點以外,也可以嘗試思考「擴充性」,例如:
  • 想一想:你是怎麼切換清單/卡片模式的,有沒有能優化的空間?
  • 進一步想想看,如果未來還要加入第三種、第四種顯示情境,你目前的邏輯設計有擴充空間嗎?會不會到時候要打掉重練?
另外,也可以思考一下目前的邏輯如何查找 DOM 元素內容,有沒有更有效率的方式?
  • 是否能穩定的切換頁籤而不會影響畫面(通常會和資料流有沒有處理好有關)
  • 嘗試對 button 做一些 hover 處理以提升用戶體驗

Step 1:

第一步老樣子,先從HTML下手吧!先將Font Awesome按鈕的樣式置入頁面中,並且調整至適當的位置。
加入icon
加入icon
說明: 要先將Font Awesome的JS先置入head裏頭。之後在Font Awesome裡尋找相關icon的class碼,安排它在Html的位置,也要適時的調整Row或col(Boostrap開發模式),最後別忘了給他們的父層,以及各自都加上屬於自己的id。
將Font Awesome的JS先置入head裏頭
安排icon在html的位置

Step 2:

再來製作出清單模式在畫面上應該顯示的樣式。
清單模式
只要先寫出一列的樣板模式即可,因為之後要用JS把設定好的HTML格式資料至入到畫面上。

Step 3:

改造function。
首先我們可以複製renderMovieList這個函式,並將它命名為renderMoviesList2之後方便做測試,基本上函式內的邏輯都一樣,只要將新寫的HTML格式資料帶到到rawHTML即可。所以去HTML把你剛剛寫好的格式放進rawHTML吧,記得要把電影名稱或相關要顯示的資料,替換成正確的參數。 之後可以將最下方renderMovieList改成renderMovieList2,來看看是不是正確顯示在螢幕上。
rawHTML的template literal置入新的格式
成功畫面

Step 4:

新增監聽器。
在Step 1置入icon的時候,就將各自及父層都設定好了id。 所以先回到上頭設定常數,將各自的位置選擇出來。
把格式按鈕位置選擇出來
然後在父層掛上監聽器。 這邊我設定的父層為btnShowStyle
btnShowStyle新增監聽器
  1. 因為在按鈕上有設置a標籤,所以要先取消超連結本上的預設動作。
  2. 加入判斷式,確定是選擇到哪一個按鈕。
  3. 接著變更圖案本身的顏色樣式,因為是使用boostrap系統,所以要將各自的classList做新增或刪除。(使用狀態下為藍色primary,非使用狀態下為灰色secondary)
  4. 最後面的renderMovieList記得改成renderMovieList2
最後來檢查按鈕是否有成功,此時按下按鈕,按鈕要會變色,且會變換顯示的模式

Step 5:

優化顯示模式的語法。 由於現在將兩個不同的顯示方式分成兩個函式來寫,會增加後面管理程式碼的困擾,因為只要碰到任何跟渲染畫面"renderMovieList"的時候,都要去判斷要用renderMovieList或是renderMovieList2,包含查找功能,換頁功能都有用到renderMovieList這個函式,為了不去更改原有的程式碼,所以決定把這兩個函式合併。
先將renderMovieList2內的程式碼先搬到renderMovieList後面, 接著就是加入判斷式, 這邊思考後,我的想法是先在最上頭新增一個變數 showStyle作為信號開關,
showStyle作為信號開關
接著在renderMovieList加上判斷式,若showStyle等於0時,使用cards的顯示方式,否則就顯示清單模式。
加上判斷式
接著回到顯示模式監聽器,加入當選則卡片時showStyle重新賦值為0,選擇清單時,showStyle重新賦值為1。
依照選擇不同的按鈕,重新賦值showStyle
最後檢查一遍把確定所有的renderMovieList不要有出現之前寫的renderMovieList2。
現在頁面已經可以順利切換了,而且也優化了程式碼,未來若要新增第三種第四種顯示方式,只要在renderMovieList內新增新的判斷及格式,還有在樣式顯示監聽器內加入新的判斷就可以了。
目前原有的功能也要都能夠正常運作,只要選定一種顯示方式,不管用搜尋、換頁都會保持原有的顯示方式。
但是發現一個小問題,當我在卡片狀態下然後在第三頁時,當我按下變換樣式顯示頁面內容會回到第一頁,應該要顯示當頁才對。
這時候回頭檢視所有的renderMovieList帶入的引數發現,全部都帶入了getMoviesByPage(1),所以不管搜尋、換頁,只要碰到getMoviesByPage(1)帶入的是1時,全都會回到第一頁。

Step 6:

修正所有的getMoviesByPage(1),除了搜尋監聽器內的getMoviesByPage(1)。
回到最上方設定一個新的變數page 且賦予值 1。
新變數page 賦予值 1
再來將所有的getMoviesByPage的引數帶入page getMoviesByPage(page) 這邊要注意,除了搜尋監聽器內的getMoviesByPage(1),不能修改。 然後在回到之前頁碼生成的函式內,將原本的定義page為變數的let拿掉。
原本的 let page = 的let拿掉
現在只要切換頁面就會給page重新賦值,page被確定下來,就算換樣式,也還是會保持在原本該顯示的頁數了。 除了搜尋監聽器內的getMoviesByPage(1)不能改原因 因為現在page在globle的狀態,假設一開始先切換到第三頁,page值此時會被賦予3,搜尋監聽器內的getMoviesByPage()引數如果是page的情況下''renderMovieList(getMoviesByPage(page))'',這時候搜尋任何關鍵字,搜尋結果是少於三頁的情況下,會發現此刻畫面會變一片空白沒有資料,那是因為我們變成渲染頁數變成第三頁,但是結果少於三頁,所以當然就沒有任何電影顯示出來。
所以再次強調

除了搜尋監聽器內的getMoviesByPage(1),不能修改。 除了搜尋監聽器內的getMoviesByPage(1),不能修改。 除了搜尋監聽器內的getMoviesByPage(1),不能修改。

已完成任務 (已完成的畫刪除線)
  1. 要新增一組功能按鈕,可以將畫面呈現為列表模式及卡片模式。
  2. 畫面能夠順利在 list 和 card 模式間來回切換。
  3. 不能影響到原有功能(尤其是 More、收藏按鈕、分頁功能要正常運作)
  4. 由於程式碼篇幅頗長,請運用 description 欄位說明新增的功能,幫助助教能有效注意到重點。在程式碼中也請運用註解來提示助教!

已完成的視覺與使用者動線驗收重點 (已完成的畫刪除線)
  • 切換顯示模式時,內容能停留在原本的頁面,不會跳回第一頁
  • 若使用搜尋後,再切換顯示模式,仍然能正常顯示搜尋結果
  • 視覺上能讓使用者知道現在選的是第幾頁、哪個顯示模式、哪些項目有加入收藏
看來只剩下最後兩項了,加把勁!

Step 7:

讓使用者知道現在選的是第幾頁。
隨著改變頁數要改變頁碼的顯示樣式,這代表每當我選了一次頁碼,我勢必要重新渲染一次頁碼,所以表示一定會是從這兩個部分下手
  1. renderPaginator(在正確的頁數上改變樣式)
  2. 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保留之前的搜尋結果,將會出現顯示錯誤電影資料。 最後再補上一個執行產生頁碼函式。
記得要清空filteredMovies
這樣讓使用者知道現在選的是第幾頁就大功告成啦!

Step 8:

顯示哪些項目有加入收藏。
這大概是所有題目內,我覺得最困擾的一個題目了,邏輯性比較複雜。 我思考的邏輯是,先製作一個新的function: 一開始先設定幾個常數:
  1. 選出所有class為card-title的元素(應該有12個,因為每頁顯示12筆),並放入panelMovies,之後就可以使用panelMovies[i].innerText來取得畫面上的電影名稱。
  2. 將我最愛的電影從locoalStorage取出並從JSON轉成Object,並放入favoriteMoviesList
  3. 將favoriteMoviesList使用map製造出一個新的陣列,條件是每一筆電影資料的電影名稱,並放入favoriteMoviesTitle
  4. 重複畫面上總共有幾部電影,就重複檢查多少次,for迴圈
  5. 加入判斷式,若favoriteMoviesTitle裡面含有畫面上第i部的電影名稱,修改"新增至我的最愛按鈕"的顯示樣式。
新增一個函式來做已收藏確認
補充說明:
  1. 第140行,當選擇到元素標籤時,可以使用setAttribute(’string’,’value’)來設定新的標籤屬性,兩個引述都是字串,屬性無值時為空字串。
  2. 對陣列使用map(),會將陣列中每一個項目,依照條件,產生一組新的陣列
MDN範例說明

大功告成,完成了所有作業要求了! 最後再檢查一遍作業的批改標準吧! 詳細的檢查一遍,操作看看,有沒有發現其他的小錯誤,若沒有大致上應該沒有問題啦!

分享至
成為作者繼續創作的動力吧!
© 2024 vocus All rights reserved.