# SDPM前端每周教學共筆筆記
###### tags: `前端教學`
[TOC]
## 2023-04-28
### 教學大綱
* 介紹API串接工具
* AJAX
* Fetch
* Axios
* API串接實作
* 從後端串接API (範例網站 : https://jsonplaceholder.typicode.com/)
* 如何序列化表單
* FormData
* 介紹HTTP動詞
* GET、POST、PUT、DELETE
* 封裝API串接流程
### 作業
使用Fetch或Axios,針對HTTP動詞進行API Library封裝。
後端github : https://github.com/kai890707/test_backend
API說明 :
先將專案clone到本地,下composer install,使CI4能跑起來。
API GET 測試請用 => localhost:8080/user
API POST 測試請用 => localhost:8080/user
API PUT 測試請用 => localhost:8080/user/1
API DELETE 測試請用 => localhost:8080/user/1
PUT跟DELETE請求網址後方的1沒有太大的意義,單純只是為了呼應Restful API的設計規範,但呼叫API時還是需要帶入。
案例說明 :
如果使用DELETE動詞進行請求,成功的話應該會拿到下圖的Object。

進階API
[ POST ] localhost:8080/plus/
[ PUT ] localhost:8080/plus/1
上述兩個API分別接收FormData與JSON。
如果POST正常發出API的話會收到的結果如下:

如果PUT正常發出API的話會收到的結果如下:

兩者差異在於POST的API吃的資料是formData,PUT吃的資料是JSON
可參考這篇文章找出作法 : https://jasonwatmore.com/post/2021/09/20/fetch-http-put-request-examples
<font color="red">
註1: 需要將作業上傳到github 、 然後把連結貼上來。
註2: 留下你們在做這份作業時遇到的問題或是不一樣的實作方法。
註3: 使用下方格式留言
</font>
:::success
* 姓名
* 作業github
* 遇到的問題
:::
--------------------------------------------------------
:::success
* 林愷容
* 作業github:https://github.com/HUANZILin/test_backend
* 遇到的問題:
1.不知道怎麼在js調用ci4.env的變數
2.把FormData變成JSON(解決方法:https://stackoverflow.com/questions/22195065/how-to-send-a-json-object-using-html-form-data)
* 4/28(五)筆記
* API串接
1. Fetch()方法(回傳一個Promise)
fetch(url, {
method:""
}).then((res)=>{
return res.json();
})**.then(res1=>{
console.log(res1);
});**(這裡是接住前面的Promise)
傳回的資料會包含在body裡面
2. axios(推薦)是一個物件
使用方法:(要先引入CDN) axios.get(url,{});
傳回的資料會在data裡面
* FormData()
* 可以把form變成物件,可以透過get()取得input的**name標籤**對應的value
* 透過監聽事件觸發,不要用表單裡面的action,再利用preventDefault()攔截資料,可以先處理過資料再送進後端
* API請求function的封裝
* 用一個物件把GET, POST, DELETE等等通通包好,其中重複的參數如url跟data可以一併拉出來寫
:::
:::info
* 姓名: 藍璟儀
* 作業github: https://github.com/jinny8813/homework
* 遇到的問題: 剛開始以為要連範例的Api,所以撞牆了一下XD寫完後再回來看一次好像更懂了
* 參考資料:
* https://ithelp.ithome.com.tw/articles/10304656
* https://stackoverflow.com/questions/41431322/how-to-convert-formdata-html5-object-to-json
:::
:::warning
### 關於把FormData變成JSON
* 愷容的方法:

* 璟儀的方法:

* MDN

* 結論:都是把鍵值對列表結構變成Object,再用JSON.stringfy()變成JSON
:::
## 2023-05-05
### 教學大綱
* 理解 CORS & RESTful API
* 理解 SPA
* 看React教學影片
-----------------------------------------------------
:::success
### 5/5(五) CORS & RESTful API 研究筆記(一)
* **CORS(Cross-Origin Resource Sharing)是什麼?**
直接翻譯成中文叫做「跨來源資源共用」,是一種讓使用者得以存取其他網域資源的機制/規範。
* **為什麼需要CORS?**
基於瀏覽器的**同源政策(Same-Origin Policy)**,因為安全性的考量,只有請求相同來源的資源可以被存取,否則必須遵守CORS。
*同源:相同的Protocal, Domain and Port
* **CORS是怎麼運作的?**
標準的做法是加入**HTTP標頭**描述跨網域資源的來源資訊,根據不同的HTTP方法,HTTP標頭的內容也不盡相同。其中會對伺服器原本資料產生影響的請求(ex: PUT, DELETE),規定必須要在傳送實際請求之前先傳送**預檢(preflight)請求**。
* **簡單請求**
* HTTP方法:GET, POST, HEAD
* Client端標頭:Origin(跨域資源來源)
* Server端標頭:Access-Control-Allow-Origin(允許的來源)
* **需預檢請求**
* HTTP方法:PUT, DELETE, CONNECT, OPTIONS, TRACE, PATCH, 其他特例(ex: Content-Type: application/json)
* 預檢請求為HTTP OPTIONS方法
* Client端標頭:Access-Control-Request-Method、Access-Control-Request-Headers
* Server端標頭:Access-Control-Allow-Methods、Access-Control-Allow-Headers
* **附帶身分驗證的請求(ex: 包含Cookies的請求)**
* Client端根據不同發送方法需要不同的設定,關鍵字:credentials
* Server端標頭:Access-Control-Allow-Credentials
\*Server端的Access-Control-Allow-Origin不能為*
* **參考資料**
* [跨來源資源共用(CORS)-HTTP|MDN](https://developer.mozilla.org/zh-TW/docs/Web/HTTP/CORS)
* [[教學] 跨來源資源共用(CORS)解析:如何正確設定 CORS?](https://shubo.io/what-is-cors/)
* (未讀)[CORS 完全手冊(一):為什麼會發生 CORS 錯誤?](https://blog.huli.tw/2021/02/19/cors-guide-1/)
:::
:::success
### 5/5(五) CORS & RESTful API 研究筆記(二)
> API定義了Client端如何取得資源的規範,而RESTful API是實踐了REST架構進行設計的API。
* **REST(Representational State Transfer)是什麼?**
REST是一種軟體架構風格,具有以下特性:
* 統一介面:唯一的URL名稱,使用HTTP方法進行定義,定義取得資源的呈現方式等等
* 無狀態:Client端可以依照任何順序請求資源
* 分層系統
* 可快取性:支援快取增加效能,避免浪費流量
* 隨需編碼:可以臨時擴充Client端功能
* **使用RESTful API的好處**
* 幫助除錯
* 各資源實體之間的相依性低
* 擴展功能不會降低效能
* **RESTful API的內容**
* URL
* HTTP方法
* HTTP標頭
* **參考資料**
* [什麼是RESTful API?](https://aws.amazon.com/tw/what-is/restful-api/)
* [從無到有打造 RESTful API service](https://ithelp.ithome.com.tw/users/20091343/ironman/762)
* [RESTful API 設計準則與實務經驗](https://www.webguide.nat.gov.tw/News_Content.aspx?n=531&s=2918)
* (未讀)[何謂RESTful API?](https://dotblogs.com.tw/jeffyang/2018/04/21/233001)
:::
:::info
- CORS
- CORS (Cross-Origin Resource Sharing): 讓網頁資源能夠被其他域名頁面存取的一種機制
- 同源政策 (Same-Origin Policy): 非同源的 request 會因為安全性考量受到限制
- 相同的通訊協定 (protocol)
- 相同的網域 (domain)
- 相同的通訊埠 (port)
- [https://zh.wikipedia.org/zh-tw/跨來源資源共享](https://zh.wikipedia.org/zh-tw/%E8%B7%A8%E4%BE%86%E6%BA%90%E8%B3%87%E6%BA%90%E5%85%B1%E4%BA%AB)
- ⭐[https://shubo.io/what-is-cors/](https://shubo.io/what-is-cors/)
- restful api
- REST/RESTful (Representational State Transfer): 一種網路架構風格
- RESTful API: 在網頁中使用 REST 概念被實作出來的 API
- 資源的操作: CRUD對應HTTP Request的GET、POST、PUT、DELETE方法
- 以不呈現對資源(url)的操作(無狀態)的方式,定義url
- 架構限制
1. 客戶端-伺服器(Client-Server): 關注點分離
2. 無狀態(Stateless): 伺服器不能儲存客戶端的資訊
3. 快取(Cacheability):回覆必須表明本身是否可以進行快取
4. 統一介面(Uniform Interface): 減少了耦合性,可以讓所有模組各自獨立的進行改進
5. 分層系統(Layered System): 中間伺服器可以通過負載均衡和共享快取的機制提高系統的可延伸性
6. 按需代碼(Code-On-Demand,可選): 臨時性的擴充功能或者客製化功能
- Url命名範例
Bad: /getProducts
Good: GET => /products/13579
- [https://medium.com/itsems-frontend/api-是什麼-restful-api-又是什麼-a001a85ab638](https://medium.com/itsems-frontend/api-%E6%98%AF%E4%BB%80%E9%BA%BC-restful-api-%E5%8F%88%E6%98%AF%E4%BB%80%E9%BA%BC-a001a85ab638)
- [https://zh.wikipedia.org/zh-tw/表现层状态转换](https://zh.wikipedia.org/zh-tw/%E8%A1%A8%E7%8E%B0%E5%B1%82%E7%8A%B6%E6%80%81%E8%BD%AC%E6%8D%A2)
- [https://ithelp.ithome.com.tw/articles/10191925](https://ithelp.ithome.com.tw/articles/10191925)
- [https://hackmd.io/@monkenWu/Sk9Q5VoV4/https%3A%2F%2Fhackmd.io%2F%40gen6UjQISdy0QDN62cYPYQ%2FHJh9zOE7V?type=book](https://hackmd.io/@monkenWu/Sk9Q5VoV4/https%3A%2F%2Fhackmd.io%2F%40gen6UjQISdy0QDN62cYPYQ%2FHJh9zOE7V?type=book)
:::
## 2023-05-12
### 教學大綱
* 理解 DOM 渲染流程
* 理解 React 生命週期
* 參考網址 : https://react.dev/
* 參考網址 : https://gyx8899.gitbook.io/blog/react/react
-----------------------------------------------------
:::success
### 5/12(五) React生命週期(Class Component) 研究筆記

> 生命週期流程圖完整版:https://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/
React的生命週期可以被分成三個階段:Mounting(安裝)、Updating(更新)、Unmounting(移除),在不同的階段React會呼叫相應的方法。
*所有方法中,render()是唯一必須實作的方法
* **Mounting**
* 時機:當component被創建並安插進DOM中時
* 方法:constructor()→getDerivedStateFromProps()→render()→**componentDidMount()** **(render完成)**
* **Updating**
* 時機:當component因為state或是props改變而重新渲染時
* 方法:getDerivedStateFromProps()→shouldComponentUpdate()→render()→getSnapshotBeforeUpdate()**(render完成)** →**componentDidUpdate()**
*如果沒有設定條件,只要任何一個props/state被更新就會重新進入Update週期
* **Unmounting**
* 時機:當component被從DOM中移除時
* 方法:**componentWillUnmount()**
* **(待補)Function Component**:使用useEffect()
*component是一組JS function,而React渲染畫面的方式是從父元件開始依序往下call functions,這個過程總共只會進行一次。React中使用useState()來觸發再次渲染
* **參考資料**
* [React 组件生命周期](https://www.runoob.com/react/react-component-life-cycle.html)
* [Component的狀態State及生命週期Lifecycle](https://ithelp.ithome.com.tw/articles/10200767)
* [【React.js入門 - 16】 React生命週期(1/4): Mount(上)- 在渲染以前](https://ithelp.ithome.com.tw/articles/10221346)
* [Adding lifecycle methods to a class component](https://react.dev/reference/react/Component#adding-lifecycle-methods-to-a-class-component)
:::
:::success
### 5/12(五) SPA/SSR 研究筆記
* **SPAs(Single-Page Applications)單頁應用程式**
在初始請求之後,Server端只傳送一份HTML文件,接下來使用JavaScript(AJAX)操作並改變所有可視元件。
因為前端專注在頁面的呈現方式,後端負責處理資料,所以是**前後端分離**,通常會搭配MVC架構進行更明確的職權切割。
* **使用時機**:切換畫面時有常駐服務(ex:YouTube)
* **優點**
* 更流暢的UI/UX
* 降低伺服器負擔
* **問題**
* 第一頁需要較長反應時間載入JavaScript
* SEO(Search Engine Optimization)表現差
* 複雜的狀態管理(ex:拿到資料前後的畫面)
* **前端SPA框架**:Angular, React, Vue
---

* **SSR(Server Side Render)伺服器端渲染**
傳統將每個功能做成HTML文件,再一一由Server端渲染出來的方式就是SSR的一種,但會造成Server端負載過大。
現代為了解決SPA的SEO問題,轉變成**先在Server端渲染第一頁**讓爬蟲爬,剩下再跟SPA一樣交由Client端渲染(Client Side Render)。使用Isomorphic JavaScript/Universal JavaScript,在同一份JavaScript中同時實作前後端的邏輯。
* **前端SSR框架**:Next(React), Nuxt(Vue)
* **參考資料**
* [前端三十|18. [FE] 為什麼網站要做成 SPA?SSR 的優點是什麼?](https://medium.com/schaoss-blog/%E5%89%8D%E7%AB%AF%E4%B8%89%E5%8D%81-18-fe-%E7%82%BA%E4%BB%80%E9%BA%BC%E7%B6%B2%E7%AB%99%E8%A6%81%E5%81%9A%E6%88%90-spa-ssr-%E7%9A%84%E5%84%AA%E9%BB%9E%E6%98%AF%E4%BB%80%E9%BA%BC-c926145078a4)
* [跟著小明一起搞懂技術名詞:MVC、SPA 與 SSR](https://hulitw.medium.com/introduction-mvc-spa-and-ssr-545c941669e9)
* [前後端分離與 SPA](https://blog.techbridge.cc/2017/09/16/frontend-backend-mvc/)
* [搞懂前端技術名詞 SSR與SPA](https://medium.com/web-design-zone/%E6%90%9E%E6%87%82%E5%89%8D%E7%AB%AF%E6%8A%80%E8%A1%93%E5%90%8D%E8%A9%9E-ssr%E8%88%87spa-450563784c47)
* (未讀)[Rendering on the Web](https://web.dev/rendering-on-the-web/)
:::
:::info
### DOM渲染流程
* 核心渲染流程(Critical Rendering Path,簡稱 CRP)
* Document Object Model (DOM)
* 瀏覽器讀取HTML檔案,將HTML元素建構成一個JavaScript物件"Node"的樹狀結構(DOM tree)
* DOM中的節點未必是HTML元素,包含註解、屬性、文字等等
* DOM不包含在JS標準中,DOM屬於高階的WebAPI的一部份
* CSS Object Model (CSSOM)
* 它與DOM相似,也是一個樹狀的資料結構(CSSOM tree)
* CSSOM tree不包含不會顯示在畫面中的元素
* Render tree
* 結合了DOM tree以及CSSOM tree,在render tree建構完成前,畫面上不會有任何內容。
* Layout
* 排版。又稱作reflow或是browser reflow
* layout thrashing (頻繁Layout造成效能的卡頓)
* Paint
* 繪圖。瀏覽器並不會依序繪製每一個layer
* 為了增進效能,瀏覽器可能會開啟多個線程(thread)來執行點光柵化
* Compositing
* 組合。許多將被依序繪製到畫面中的layer(點陣圖格式)透過GPU被繪製到螢幕中。
* 參考資料
* [How the browser renders a web page? — DOM, CSSOM, and Rendering](https://medium.com/jspoint/how-the-browser-renders-a-web-page-dom-cssom-and-rendering-df10531c9969#id_token=eyJhbGciOiJSUzI1NiIsImtpZCI6IjgyMjgzOGMxYzhiZjllZGNmMWY1MDUwNjYyZTU0YmNiMWFkYjViNWYiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJuYmYiOjE2ODQyODg3NjcsImF1ZCI6IjIxNjI5NjAzNTgzNC1rMWs2cWUwNjBzMnRwMmEyamFtNGxqZGNtczAwc3R0Zy5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbSIsInN1YiI6IjEwODY4MDk1MTIzNjExNTI3MjAyMiIsImVtYWlsIjoiamlubnk4ODEzQGdtYWlsLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJhenAiOiIyMTYyOTYwMzU4MzQtazFrNnFlMDYwczJ0cDJhMmphbTRsamRjbXMwMHN0dGcuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJuYW1lIjoiY2hpbmd5aSBsYW4iLCJwaWN0dXJlIjoiaHR0cHM6Ly9saDMuZ29vZ2xldXNlcmNvbnRlbnQuY29tL2EvQUdObXl4YWNDUlpoT2xXWUs1ZkxXbkYxaDBfMUNrMmprYzdhZ1hwY3p5bk9UUT1zOTYtYyIsImdpdmVuX25hbWUiOiJjaGluZ3lpIiwiZmFtaWx5X25hbWUiOiJsYW4iLCJpYXQiOjE2ODQyODkwNjcsImV4cCI6MTY4NDI5MjY2NywianRpIjoiOWVkMDA0ZDQyMmZlMDE3MzJmNDVjOWI3NGU1ZWI2Mzk2ZWIzMzQwZCJ9.r0_YQYn2TI32SVYJiriMHr59j6tQMPG6DhfW_dl_ZAEbOOsh8-S_DxDTf2ck0zXAwKNa-7jbCZXCvx0tt2pNjRtbzfilZytiscWGOIN4Lw2lZpx3YsydgCTpWePmIILY78xXTHSc19WTURWzxtmG9R06MwnMUj-GcSYJgedghEQ5rFHoq0dF0ksDWtEBmnsFiByaRpG5nxjhciv1CgYnsIB5KvBpcv8uw5aQJA1OUrvFbb2FI-2HdfYsWkXNQyN2YAURGwAkukWpN1aZAJFBWSOuKOhKoFQjUz_4hWDFtZTHt01cmvvzFDBYyMkcuytGvh-L6GMS7XB2fY79WwUT8Q)
* [Populating the page: how browsers work](https://developer.mozilla.org/en-US/docs/Web/Performance/How_browsers_work)
### React生命週期
* 參考資料
* [React 學習筆記 3 — 聊聊元件的生命週期與 Hooks](https://medium.com/%E6%8A%80%E8%A1%93%E7%AD%86%E8%A8%98/react-%E5%AD%B8%E7%BF%92%E7%AD%86%E8%A8%98-3-%E8%81%8A%E8%81%8A%E5%85%83%E4%BB%B6%E7%9A%84%E7%94%9F%E5%91%BD%E9%80%B1%E6%9C%9F%E8%88%87-hooks-529a4d70f5a6)
* [React lifeCycle 生命週期](https://medium.com/coding-hot-pot/react-lifecycle-%E7%94%9F%E5%91%BD%E9%80%B1%E6%9C%9F-a48683ae3922)
* [The React lifecycle: methods and hooks explained](https://retool.com/blog/the-react-lifecycle-methods-and-hooks-explained/)
:::
## 2023-05-19
### 教學大綱
* React影片學習進度彙整 - 第5、6節
* 學習到React的什麼方法 ?
* 這些方法所代表的意義是什麼?
* 有什麼作用?
* 它的底層實現方法是什麼? 像是useState()就是getter跟setter的封裝
---
:::success
### 5/26(五) Shadow DOM 研究筆記
Shadow DOM是實現Web components封裝的關鍵API,可以將HTML標籤的結構、樣式和行為隱藏,附加到DOM tree的節點上,並與其他節點分割開來,使程式碼更加簡潔。
* **Shadow DOM中的術語**

* **Shadow host**:Shadow DOM附加的常規DOM節點。
* **Shadow tree**:Shadow DOM 內部的 DOM tree。
* **Shadow root**: Shadow DOM tree的跟節點。
* **Shadow boundary**:Shadow DOM結束的地方,也是DOM開始的地方。
* **Shadow DOM的操作**

就和操作常規DOM一樣,可以添加子節點、設置屬性,以及為節點或者整個Shadow DOM增加樣式。不同的是,Shadow DOM內部的元素不會影響到外部的元素(除了:focus-within)。另外,不是所有DOM節點都可以被附加Shadow DOM(許可的標籤見上圖)。
* **方法**:
`let shadow = this.attachShadow({mode: 'open'});//可以從外部訪問`
`let shadow = this.attachShadow({mode: 'closed'});//不能從外部訪問`
* 將Shadow DOM附加到元素之後,就可以使用DOM APIs對它進行操作(ex:appendChild(), setAttribute())
* **Shadow DOM的使用場景**
* 瀏覽器內建的原生components
* Custom Elements
* HTML Templates
* Micro Frontends
* **參考資料**
* [使用 shadow DOM](https://developer.mozilla.org/zh-CN/docs/Web/API/Web_components/Using_shadow_DOM)
* [微服務很夯,那你有聽過微前端嗎?初探 Micro Frontends 程式架構](https://medium.com/starbugs/%E5%BE%AE%E6%9C%8D%E5%8B%99%E5%BE%88%E5%A4%AF-%E9%82%A3%E4%BD%A0%E6%9C%89%E8%81%BD%E9%81%8E%E5%BE%AE%E5%89%8D%E7%AB%AF%E5%97%8E-%E5%88%9D%E6%8E%A2-micro-frontends-%E6%9E%B6%E6%A7%8B-e0a8469be601)
:::
:::success
### 6/2(五) React影片學習進度彙整
* **useState**:useState returns 一個 array,包含兩個值分別為目前的 state(第一次渲染的值會是useState()設定的值),以及一個set function 用來更新 state 以觸發 re-render。
* **prevState**:prevState用來訪問前一個state的值,在必須更新舊元件的狀態時使用,根據變數名稱改為prev+大寫開頭變數
* **Key**:在render array(list)的時候,如果沒有加key,React會把新的元素加到最後,再重新排序,對於效能不好也會導致重新排序時,若有元素中有state可能遺失的bug,所以標籤內建key屬性讓React辨識
* 比較**React四種設定樣式的方法**:inline style, class, class module, styled-components
* **inline style**:層級太高了,不夠簡潔
* **class**:每個class名稱都是全域的,無法切割
* **class module**:命名為「名稱.module.css」,會在原本的class名稱後面加亂碼,可以做區域的區分,使用時用object取attribute的方式
* **styled-components**:react的package(要先install並import),css in js的寫法,寫完的css最後會一起打包成一個唯一的亂碼class名稱
* 一次只能return一個root node,有多種方法可以達成:div、Wrapper(props.children)、React.Fragment(預防div soup)

* **Portals**:可以指定node在DOM tree中進行渲染的位置
* **Refs**:Reference的縮寫,useRef()的props永遠指向設定其ref的物件(一個DOM node),不會對渲染產生影響,但可以對已被渲染的節點進行操作(不建議),如果只是單純想要讀取建議使用ref。
* ref不能在function component中使用,除非藉由useInperativeHandle()以及在要使用ref的component使用React.forwardRef()並傳入props(ref)
* (6/22更新)**useEffect**:
* **什麼是Side Effects?** 所有除了頁面渲染以及針對user input處理的部分,比如Http request或是對user input變動的即時應對
* useEffect()中包含兩個部分:function跟dependencies,其中function可以是name function或是arrow function,而dependencies以[]列出觸發function的相依變數,如果[]為空,則只會在第一次render結束後執行一次
* useReducer:當需要複雜的state管理機制時,例如一個state的更新關聯至另一個state,可以使用useReducer
* useContext:
* **什麼是Context?** 若是不同功能的components之間有許多需要透過props傳值的物件,因為必須先lifting到彼此互通的parent component而不能直接互傳,會導致props chain變複雜,所以藉由Context可以事先定義好要傳遞的物件,並在最上層的component進行向下的傳遞(所有child components都能使用)。但相對的context就不適用於變動頻繁、客製化的component,比如UI中的button(click的效果不一樣)
* 相較於使用Provider&Consumer,一個更簡潔的使用Context的方式,就是在component裡面命名一個變數並使用useContext賦值
* **參考資料**
* [JavaScript Getter and Setter](https://www.programiz.com/javascript/getter-setter)
* [useState](https://react.dev/reference/react/useState)
* [createPortal](https://react.dev/reference/react-dom/createPortal)
:::