透過 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}}
如果是使用兩層 ../../
,就可以再往上一層尋找了。
重要資料
成品