# 10/18 JS Detect color game, object, JSON, JS-API
###### tags: `JS` `2021/10/18` `進度筆記` `前端心得`
---
講師: 林俊生 老師
佘昌霖 老師
---
# 先複習一下
## 常見三種 html 傳值方法:
1. onclick="doit('aa')"
2. dom 元素 抓 value
3. dara-* attribute
---
# 除了三種常見的資料, 還有甚麼傳資料的方法?
> 例如, youtuber 從後端傳資料到前端頁面, 有應用生成

# 樣版字串:
```
寫了一張卡片的樣版後, 讓JS 去幫你自動生成, 內容跟資料會根據後端傳的資料去應用
```
# 參考資料:
[鐵人賽:JavaScript Template String 樣板字串 | 卡斯伯 Blog - 前端,沒有極限 (wcc723.github.io)](https://wcc723.github.io/javascript/2017/12/22/javascript-template-string/)
[10\. ES6 - 樣板字面值 - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天 (ithome.com.tw)](https://ithelp.ithome.com.tw/articles/10243733)
[\[JS學徒特訓班\] JavaScript ES6 樣板字串(Template String) - 斜槓女紙 - Medium](https://medium.com/coding-girl-life/js-es6-templatestring-5eddbd29d8e9)
[\[JS\]Template Literals(字串樣版) - HackMD](https://hackmd.io/@chrisHsiao/BykaBsBa8)
[\[筆記\] JavaScript ES6 中的模版字符串(template literals)和標籤模版(tagged template) ~ PJCHENder<br>那些沒告訴你的小細節](https://pjchender.blogspot.com/2017/01/javascript-es6-template-literalstagged.html)
[PJCHENder那些沒告訴你的小細節](https://pjchender.blogspot.com/)
[ES6 Template Literals 字串樣版/字符串格式化 - JavaScript (JS) 教學 Tutorial (fooish.com)](https://www.fooish.com/javascript/ES6/template-literals.html)
[ES6 -- 字串樣板(String Template) (lucrelin.blogspot.com)](https://lucrelin.blogspot.com/2016/11/es6-template-strings.html)
---
# 複習 Key & Value
> 在不同的地方 key & value 的寫法也不同
> 例如:
- 陣列中
```
let carplate = ['aaa-1234', 'bbb-5789']
```
# 在物件中的 key & value
- 物件 (object)
```
let car = { // declare object
engine: '2.0',
brand: 'toyota',
size: 'big',
color: ['blue', 'gray'],
wheele: 4,
break: {
front: 'plate',
real: 'drum'
},
}
```
- 可以塞其他的資料型態 (data-type)
- 可以存很多東西, 和用分門別類的方式下去

> 拿值的方式
```
console.log(car)
car.engine = '5.0' // let value on object(attribute); 物件特定屬性的賦值
console.log(car.engine) //物件特定屬性的取用
```
- 試一下怎麼拿灰色
```
console.log(car.color[1])
```
- 怎麼拿物件中的物件?
```
console.log(car.break.front)
```

> 不是陣列不能這樣取值(不過也有取 {} 的用法)
- 物件特定屬性的取用(就像 dom)
```
console.log(car.engine)
```
- 物件特定屬性的取用(搜尋索引的方式)
```
console.log(car['brand'])
console.log(car['color'][0])
```
- 複習一下陣列
```
let garage = [carplate, car]
```
> 陣列裡面也可以放置其他陣列(變成多維陣列, 但這種比較少用)
> 多維陣列可能給值印表格才會用到
> 也可以在陣列裡面放物件
> 例如:
```
console.log(garage[1].break.real)
```

- 這種陣列包來包去包一大堆資料的方式
- 從後端來的時候會很常見到這種 key & value 的形式
# 參考資料
[【新手大哉問】property、key、value、reference,到底是什麼啦? | by Tweert | Medium](https://medium.com/@twee301/%E6%96%B0%E6%89%8B%E5%A4%A7%E5%93%89%E5%95%8F-property-key-value-reference-%E5%88%B0%E5%BA%95%E6%98%AF%E4%BB%80%E9%BA%BC%E5%95%A6-b3a83c7723e4)
[\[筆記\] 談談 JavaScript 中 by reference 和 by value 的重要觀念 ~ PJCHENder<br>那些沒告訴你的小細節](https://pjchender.blogspot.com/2016/03/javascriptby-referenceby-value.html#comment-3989590007)
[深入探討 JavaScript 中的參數傳遞:call by value 還是 reference? (techbridge.cc)](https://blog.techbridge.cc/2018/06/23/javascript-call-by-value-or-reference/)
[重新認識 JavaScript: Day 05 JavaScript 是「傳值」或「傳址」? - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天 (ithome.com.tw)](https://ithelp.ithome.com.tw/articles/10191057)
[簡單介紹JavaScript參數傳遞 (slideshare.net)](https://www.slideshare.net/YiTaiLin/java-script-63031051)
[Value vs. Reference - Step Up Your JS: A Comprehensive Guide to Intermediate JavaScript (educative.io)](https://www.educative.io/courses/step-up-your-js-a-comprehensive-guide-to-intermediate-javascript/7nAZrnYW9rG)
[JavaScript 初心者筆記: DOM - 如何用 JS 更改 HTML & CSS 屬性 - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天 (ithome.com.tw)](https://ithelp.ithome.com.tw/articles/10218025)
[物件屬性取值 | Summer。桑莫。夏天 (cythilya.github.io)](https://cythilya.github.io/2019/10/31/object-get-value/)
---
# 何謂 JSON
- 其實是一種資料交換格式
- 內容也有 key & value
> 其實資料型態是字串

> 只是這種資料格式就像物件一樣
> 例如對 json `console.log()`
```
當你從後端抓取資料 json 的時候, 你會得到的是 JSON 格式的 ''string''
```
```
如果想要轉為 object 使用, 必須轉為 JSON.parse()
→ 這函式會將 json 的格式, 也就是 string 轉為
object
```


```
用 console.log(typeof userObject)
去抓 可以得到 object 的 data-type
所以也就可以衍伸利用
console.log(userObject.address.city)
```
> 當資料使用(修改)完成後, 如有需要可以再用 JSON 的格式方式去傳到你要的地方
- 這轉成物件的過程式可逆的
```
let carJson = JSON.stringfy(car)
console.log(typeof carJson)
console.log(carJson)
```
> 
> 如果今天有上百筆資料, 慢慢取會花很多時間
> 用 JSON 可以一口氣傳遞所有資料給後端
> 讓後端儲存
# 參考資料
[JSON - 維基百科,自由的百科全書 (wikipedia.org)](https://zh.wikipedia.org/zh-tw/JSON)
---
# 練習跟中央氣象局開放資料平台串接 API
- 要先辦會員拿授權碼
- 可以指定參數再執行(不指定會全拿)
```
透過網址去拿 JSON 格式
```

> 今天會做這個
> 大概三千多行
# 參考資料
[g0v-data mirror](https://g0v-data.github.io/mirror/)
by Dave
---
# 檢討一下 - 找色塊遊戲
==第一級, 重複遊玩==


> 
> 這邊 div 沒有分行跟列
- 如果今天有變動的話
> 這個寫法會有點危險 ↓
> 
- 可以讓他變單層, 讓他一層就做完
> 
> 這樣怎麼做 ?
> 在 display flex 加上 wrap
> 其實沒有做出換行, 然後讓 JS 丟給 CSS 和 html, 讓他一直推方塊下去
---
## 試著用 function 寫法
- 做出來, 讓這邊等於 `2*2` 方塊
> 
- 然後用 for loop 去推
> 
- 接著給他在 html 下 .onclick
> 
> 就可以去推方塊, 不過會超過邊(因為沒有設邊界)~
- 接著, 要怎麼亂數產生顏色
> 
>
> 把原本 0~1 的小數(不含一), 變成0~9.9999
> 因為小數加上 match.floor 去取整數(無條件捨去)
> 所以會變成 0~9
- 所以接下來取亂數最好的方法
```
Math.floor(Math.random()*你需要的範圍) + 你的起始數字)
例如取: 1~12
起始值是 1 End(你需要的範圍) 是 12 就會是
Math.floor(Math.random()*你需要的範圍) + 你的起始數字)
1~ 12 12 1
3~ 100 98 3
```
> 
- 加進去後就有亂數了
> 
> 因為是累加 所以方塊會越來越多
- 所以在按下的時候要把上一次的方塊全部清空
> 
- 接著做一個判斷, 讓他會出現在不同區塊
> 
## 接下來想一下偵測邏輯
- 解法有很多種
1. 因為會產生一個 class 的 ans 所以讓他用 ans 去判斷
2. 讓他用全域宣告 去改變

- 如果是以 ans 的 class 做變判斷的話
> 因為是用 JS 產生的, 所以用 querySelectorALL 去抓` # main>div` 的話會抓不到
> 
- 因此用 onclick 在 html 的話, 可以把他加在 if
> 因為要按對方塊才做, 如果沒按對就不用做
> 因為只有綁 onclick 其他都沒有綁
> 也就是按對方塊才做, 因為沒有按錯方塊會發生靈異事件的選項XD

> 所以可以直接累加
- 加完分後, 在做一個方塊
> 
# 怎麼用 JS 去改顏色和 CSS
==`第二級, 2*2 不同顏色、重複遊玩`==
- 因為 div 沒有 querySelector 去抓到
- 所以可以直接加上 inline-style!
> 
- 顏色有點淡, 調整一下XD
> 
- 接下來怎麼改顏色?
1. 用 rgb 的數值
2. 怎麼寫進去
> 改顏色
> 
- 要怎麼丟值?
> 樣版字串!
> 宣告 rgb = 亂數
> 
> 如果不要顏色太淡, 可以往下降

- 因為 html 不會算空白, 所以怎麼按空白都可以(除非字串內)
> 
## 帶進樣版字串
> 用字串去串的寫法
> 
> 這種寫法可能有 bug
> 如果不是完整 html, 一次累加再帶出來可能會爆掉
> 因為用字串畫面會很亂, 所以帶上用 ES6 的新寫法
- 接著做出樣版字串
> 
> 做出樣版字串, `${} `
> 
> 這樣就做完等級二了
---
# 第三級
==`三級: 方塊數量隨遊玩次數增加`==
- 接下來要判斷方塊增加的方法
> 
> 這樣變成 2*4+1, 因為是用父層去換行
> 所以就爆了XD
1. 讓父層的框框變大, 配合子層
2. 讓裡面的框框變小, 配合父層框框
## 如果是選一的作法
- 所以父層就會變成是做方塊的時候由父層決定
> 
> 但因為這樣不能用 px, 所以用樣版字串
> 讓寬高都一起改變
> 
> 



# 第四級
==`四級: 透明度差異隨遊玩次數減少`==
- 可以加個 opacity
> 但是顏色會隨著遊玩次數變淡
- 如果第十題變淡, 分數就會是九分
> 做出樣版字串去拿值, 因為改變了顏色變淡(下個困難度)
> 
- 根據答題數來改變方塊透明度
> 來判斷分數到時麼時候, 去改變 difficulty (opacity)
> 
> 要怎麼讓遊戲平衡不錯, 這跟 UX 有關係~
# 第五級
==`五級: 增加定時、成績功能`==
- 如果做懲罰機制, 可以在 onclick 下一些機制來做處理
> 例如, 做錯會更新題目
> 
- 接著要怎麼做 "定時" 這件事情
## ==setTimeout==
> 多久時間執行一次
```
(x, y)
x → 可以是指令(字串), 或函式
y 如果是 200 → 表示毫秒, 0.2 秒
```
## ==setInterval==
> 會一直持續執行
> 而倒數計時, 應該是會一直執行的(時間一直倒扣)
```
用法跟 setTimeout 大同小異~
```
- ES6 之前的匿名函式呼叫
> 
- ES6
=>
- 傳參數的方法
> 
> 
> 不能給括符
- 使用上會有誤差累積, 誤差會逐漸擴大
- 精準度也需要微調
---
## 造成時間差異寫法
- 比較正式的寫法
> 按下按鈕後, 應該會倒數計時, 再跑 makeBlock > 
> 按下去後變 60秒
- 接著要扣秒數
> 做一個可以執行扣秒的函式
> 把 timeleft 轉換成數字
> 
> 按下後不只會給方塊, 還會扣秒數
- 但是這樣會造方塊後, 又把時間給重置了

- 讓他開始遊戲的時候再去叫 makeBlock
> 
> 
- 這樣就不會重複了
> 
> 不過有個問題, 時間會一直扣下去扣成負值
- 因此設定一下 timeleft = 0, 讓時間到了遊戲結束
> 
> 如何時間到了讓玩家不能再點?
- Za wa ru do!
- 讓時間停住
- 給個 ID 後

- 時間到了不給玩XD
> 
> 直接清空框框 XDDDDD
> 創意發想, 給個 alert 遊戲結束, 或是有其他做法? 不要清空框框~
> 
> 其實也可以不用轉數字直接印出來!
- 遊戲結束
> 
> 不過發現遊戲可以累計
- 所以按開始的時候分數要重計算
> 
```
讓參數返回(return)
```
==一個好的 code 應該把功能分開==
> 增加功能的耦合性
> 比較可以維護
> 專案化公司, 耦合性稍高, 因為是客製化
> 如果是, 耦合性比較低, 比較會有重複貼上, 也比較好維護
# ==第六級==
- 如果是 click 事件的話
- 要怎麼按下才確定

> 也沒辦法用 class 判斷(可以把 class 刪除看看~)
> 不能用外再去判斷的時候要怎麼用 code 去判斷 ?
> 依照 index 去做做看
> 
> 看 index 傳過來的數值對不對?
> 不過要怎麼用 index 去傳?
> 因為沒辦法用 queryselectorALL 去抓
- 所以在造方塊的時候, 直接檢查索引值
> 
> 並做個判斷

> 這樣會報錯, 因為 guess 的 ans 沒有定義
因為, ans 寫在 function 裡面

> 所以把 ans 拿出來
> 
# POC - 開發的時候要從小的地方開始
- Proof of concept, POC
- 確認規劃的想法, 概念, 流程是否可行~
- 設定完整體後, 做個小規模的測試
```
一個一個的測試, 如果業主一開始給得很大的東西, 也要有辦法做出從小地方開始測試
```
---
# 參考資料:
[\[筆記\]\[JavaScript\]用Math.random()取得亂數的技巧 - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天 (ithome.com.tw)](https://ithelp.ithome.com.tw/articles/10197904)
https://segmentfault.com/a/1190000016444812
https://www.jb51.net/article/118860.htm
[談談 JavaScript 的 setTimeout 與 setInterval | Kuro's Blog](https://kuro.tw/posts/2019/02/23/%E8%AB%87%E8%AB%87-JavaScript-%E7%9A%84-setTimeout-%E8%88%87-setInterval/)
[setInterval() - Web APIs | MDN (mozilla.org)](https://developer.mozilla.org/en-US/docs/Web/API/setInterval)
[JavaScript Day22 - setTimeout、setInterval - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天 (ithome.com.tw)](https://ithelp.ithome.com.tw/articles/10279012?sc=hot)
[利用setTimeout(setInterval)做簡易倒數計時器 (victsao.com)](http://victsao.com/blog/81-javascript/78-settimeout-timer)
[\[javascript\] 深入了解 setTimeout() 與 setInterval() 的不同之處 – camel 's blog (camel2243.com)](https://blog.camel2243.com/2016/08/06/javascript-%e6%b7%b1%e5%85%a5%e4%ba%86%e8%a7%a3-settimeout-%e8%88%87-setinterval-%e7%9a%84%e4%b8%8d%e5%90%8c%e4%b9%8b%e8%99%95/)
[HTML DOM setInterval() 方法 (w3school.com.cn)](https://www.w3school.com.cn/jsref/met_win_setinterval.asp)
[\[Python 常用\] 實現 setInterval 定時器圈呼叫函式功能 — 1010Code (andy6804tw.github.io)](https://andy6804tw.github.io/2021/01/21/time-interval/)
[Window setInterval() 方法 | 菜鸟教程 (runoob.com)](https://www.runoob.com/jsref/met-win-setinterval.html)
----
# 做一個類似倉儲(分類)系統
- 結合跟 JSON 的練習使用, 來做一個頁面~
# 練習導入 JSON 的格式
# 做出這個畫面

- sunyehfy good to eat
- 刻一個版面
- 進入網頁版全部商品列出來
- 按下飲料的時候只有飲料, 點主食的時候只有主食的菜單
- 有 filter, 可以去選飲料 -
- 甜點跟飲料裡面都有珍奶
> 
- 去串 JSON
> 
> 
---
# 建立一個 上益好好吃的版面
1. 先做卡片
```
1. canvas 或 display 區塊
2. nav
3. div
```
2. 需要導覽列區塊
- nav
> 
> 
> 
- main

- 請 JS 幫忙之前, 自己先做一個 demo
> 
> tag 不用印, 拿來做分類
> 
- card 的 css
> 
- card 的 html
> 
> 
- car img, div, name 樣式
> 
> 
> 
- 為了確保沒有問題, 再複製一張 來看看有沒有問題
- 
- 用 margin
> 
> 10px 還好
> 如果大 px 去推可能會偏掉
- 如果螢幕 4:3
> 
> 再多讓兩個 div 出現在 html 上 去補足 evently
> 有個小問題 rwd 4 變 2 的時候, 就要修改數值
- html 請自由發揮
> 
---
# 利用 for loop 將設計好的版面印出(相應數量)
# 印出資料到圖片上
- 這樣可以印出每筆資料
> 
> 


---
# 將卡片中的資訊 換成樣板字串
- 用 `=` 的話, 會一直被洗掉
> 
- 可以用 ``+ =`` 去製造重複推的效果
> 
- 加個 ↓
- 

- html 和 CSS 會影響到 JS 寫的方法!!!
---
# for loop 往上移會有個問題

> 會報錯
> 
> 因為程式是一行一行讀的
> 所以移到宣告前面就出是惹
---
# JS 把卡片推出來
- 像是這樣

----
# 將卡片中的資訊印出來
- 把圖片用樣版字串去接
> 把資料換上去
> 
> 會看到爆版
> 調整一下圖片 CSS
> 
---
# 綁 onclick 參數
- 在NAV上綁上onclick 事件, 並且可以使傳送條件方便判斷
> 
> 
> 
---
# 將 for loop 寫成 function
- 將 for loop 寫成 function
- 這樣可以方便 nav 上面的按鈕去做呼叫的動作

> 寫成 function, 用 show 去執行
> 
# 按下按鈕要清空一次
> 
> 每個分類可以有對應的過濾條件
> 但按下 all 甚麼都沒有
# 讓按下 all 有東西出來
- 在 innerHTML 執行前
```
使用if判斷 → "條件"是否符合 → 我們的 tag
```
- if 會加在 innerHTML 印出去之前
- 如果傳過來的值是 all
> 
# 但飲料有, 甜點沒有珍奶
> 
```
為了解決珍珠奶茶有兩個 tag,
因此用 or(||) 去判斷 tag1 跟 tag2
```
> 
> 要符合其中一個條件就印出來
> 讓 if 判斷用 || 去製造兩邊中只要一邊的值成立就印出
> 
> 
---
# 可以再更精簡一點

> 不過應該很吃效能 (Maximum call stack size exceeded)
> 再改成單行敘述
> 甚至可以去除 else
>
> 最後可以試試看, 看卡片能不能對齊
> 如果要降低效能使用可以改成這樣 ↓ (不知道為啥, 可能是 i 的判斷條件多跑一行 =, 如果純粹用 < SY\_gooodToEat\_Product.length, 有卡死的情況
> 
---
# 明天是設計課 - prototype?
# 預告下次有天氣的卡片
## 會用到 fetch
- 因為資料量很大
- 所以可能要點很多層按鈕, 才去點到資料!
- 天氣 API