透過 AC 課程作業,利用 node.js 環境加上 express 和 handlerbars 等工具進行實作,主要紀錄邏輯想法。
安裝
mkdir trash_talk  | 
設定資料
修改 package.json
"description": "新增描述",  | 
全部需要新增的資料,app.js、trashTalk.js、character.json、/views/layouts/mian.handlebars、/views/index.handlebars,css、JS 檔案/public/javascripts/<引入資料>、/public/stylesheets/<引入資料>。
邏輯講述
我的作法是經由 character.json 創造一個資料庫存放腳色及幹話數據,再藉由匯入讀取資訊。
例:{
  "腳色":[
    {
      "name": "學生",
      "name_en": "student",
      "image": "./public/img/student.jpg",
      "trash": ["0", "1", "2", "3", "4", "5"]
    },
    .
    .
    .
    .
  ],
  "共用句":[
    "一",
    "二",
    "三",
    "四",
    "五"
  ]
}
在網頁上我們可以選擇腳色,目前一次只能選擇一位,選擇資後按下 產生幹話 ,在旁邊的顯示區塊便會隨機組合句子:
- 身為一個
學生,0應該四吧! - 身為一個
學生,3應該一吧! 
腳色職業選定後,會對應到 trash 然後隨機選擇陣列中的一個值(value),再將它放到句子中應該去的位子,而共用的句子也是同樣的道理。
這邊必須使用到兩次的同樣方式的隨機選取陣列,設定一個 function 以方便使用
function randomIndex(arr) {  | 
再來要設置一個產生 trash talk 的 function
先建立一個簡單虛擬碼
function generateTrashTalk(option) {  | 
考慮到可能在預設的狀況下也有人,不選擇按產生幹話
function generateTrashTalk(job){  | 
如此便簡單設置好邏輯再來就是將 trash_talk.js 設置匯出的 function 名稱
// exports function  | 
邏輯補充
在阿全同學作業中的邏輯判斷是這樣,判斷 req.body.job 是否為 true ,也就是裡面有沒有值,如果是真,那就回傳想要的句子,如果是 false 那就回傳請選擇人物,如此一來code就完全的簡化了。
而在另一位同學駱駱作業,助教給了一個建議,可以使用 find() 方法尋找相對應的值,而 find 是 array.prototype.find 的方法,適用在尋找 array 中的 value。
MDN給了這樣的解釋是,它會尋找出在陣列中第一個符合條件的值,並且回傳 value。
而我做成的作業在尋找進 character 之後,還是一個 hash ,但是又進一步的尋找 job_en,相當只比對全部人的 job_en 而且只回傳比對到的第一個,所以在沒有多筆從重複的資料才可以使用,之後就可以這樣寫:
function generateTrashTalk(job){  | 
app.js 設定
架設伺服器配置
// 引入 express module 以及自定義檔案  | 
所以大概的設定是這樣。
補充作業回饋
在作業回饋中,助教有說到,由於在 req.body 中只有一個值,也只要取得那個值,而我的值是設定 job,所以把 option 改成 job:const job = request.body.job
const sentence = trashTalk(job)
如此一來更容易了解,在帶入 trashTalk.js 檔案的時候也更簡潔明瞭。
關於 index.handlebars
這次的實作中,遇到了一個意想不到的問題,關於迭代的模板,又得要做 if 相等的判斷該怎麼辦,目前我的作法是使用 handlebars 中的自定義 helpers
在模板中因為使用到了 <input type="radio">,而且又使用到了迭代(Iteration),導致使用一般原本套件的 if 是不足以應付的,在原本 google 得到 helper 去判斷 checked 問題以為可以一勞永逸,沒想到怎麼跑都跑不出來。
設置一個 helper,自己定義一個 function
const Handlebars = require('handlebars')  | 
並且在迭代的template中加入
{{ifEquals option.job this.job}}  | 
這時候就遇到了麻煩了,由於我是使用
{{#each}}{{/each}}  | 
在跑作用域的時候,option 也就是app.js中 req.body 的值,這個變數在index.handlebars 中根本無法取得,在傳入 function 中的會變成 undefine 是個空的資訊。
為什麼會這樣呢?主要原因出在作用域(scope)時,在我的實作中,使用了 each 每一層的 this 不同,下一圈的時候 this 改變了,而 option 則是存在父層,得跳出迴圈去尋找父層(parent context)資訊,藉由詢問 Mike 才得以解決這個問題,尋找到的 stack overflow資料
關鍵字為express handlebars each two argument
可以看到使用了 ../ 這個往上層移動,最後在 template 中想要放置的位置改成{{ifEquals ../option.job this.job}}
如果是使用兩層 ../../,就可以再往上一層尋找了。
重要資料
成品