# NodeJS(Max)第 9 節: Dynamic Routes & Advanced Models > Udemy課程:[NodeJS - The Complete Guide (MVC, REST APIs, GraphQL, Deno) ](https://www.udemy.com/course/nodejs-the-complete-guide/) `20231216Sat.~20231218Mon.` :::danger 9-119 req.params 9-124 req.query 9-122 form的用法 ::: ## 9-119. Extracting Dynamic Params 想讓router接收動態的資料,而Express router可以幫助我們接收動態資料,透過關鍵詞`:變數名稱`,用冒號加上變數名稱即可成功(變數名稱即我們的動態資料,例如說id) :::success 注意!有兩個path路徑假如都為products,只是其中一個後面放動態資料,一個放一般的route,要記得把一般的route優先擺放在前面。 因為若是動態擺在前面,則express會把一般route也認作是動態資料的其中一筆資料,也就不會去執行一般的route了。 正確方法如下所示: ```javascript! //一般route > 擺前面!才不會被動態的吃掉 router.get('/products/delete', 這裡是middleware的位置); //動態route ":productId" router.get('/products/:productId', 這裡是middleware的位置); ``` ::: 除了需要express router中的關鍵字「冒號&變數名稱」外,還需要在controller中利用"request.params"物件。 > 可以參考[Express官方文件](https://expressjs.com/en/guide/routing.html)Route parameters的部份: ![2023-12-16 16-16-05 的螢幕擷圖](https://hackmd.io/_uploads/ryvbT05Lp.png) **▎routes/shop.js** 我們首先在routes底下的`shop.js`中定義路徑,其中運用到了「路由參數(Route parameters)」,也就是先前提到的express roter關鍵字`:變數名稱`: ```javascript! router.get('/products/:productId', shopController.getProduct); ``` **▎controllers/shop.js** 接著來到controllers底下的`shop.js`中,透過request的params物件,得到route parameter相對應的key(此處想取得的key就是productId),而我們要的就是該key的值。 ```javascript! exports.getProduct = (req, res, next) => { const prodId = req.params.productId; res.redirect("/"); } ``` :::info 所以再複習一次,request的params物件中,會抓取所有的路由參數(route parameters),將路由參數的名稱作為key存放在裡頭。(可參考前面的到的網站[Express官方文件](https://expressjs.com/en/guide/routing.html)Route parameters的部份): ![2023-12-16 16-57-05 的螢幕擷圖](https://hackmd.io/_uploads/B1UdLJjLa.png) 我覺得光是這張圖就超級清楚! ::: ![image](https://hackmd.io/_uploads/SJkKE1iL6.png) **** ## 9-120. Loading Product Detail Data > 參考資料:[JavaScript 陣列處理方法 [filter(), find(), forEach(), map(), every(), some(), reduce()]](https://www.casper.tw/javascript/2017/06/29/es6-native-array/) ![image](https://hackmd.io/_uploads/rkXJpJiU6.png) **** ## 9-122. Passing Data with POST Requests > 1. [W3C對form的定義](https://www.w3.org/TR/html401/interact/forms)(含form裡的tag:input, textarea...) > 2. [[Node.js] HTML Form如何設計、GET和POST方法的不同、如何透過express req.query, req.body取得資料](https://johnnychang25678.medium.com/node-js-html-form%E5%A6%82%E4%BD%95%E8%A8%AD%E8%A8%88-get%E5%92%8Cpost%E6%96%B9%E6%B3%95%E7%9A%84%E4%B8%8D%E5%90%8C-%E5%A6%82%E4%BD%95%E9%80%8F%E9%81%8Eexpress-req-query-req-body%E5%8F%96%E5%BE%97%E8%B3%87%E6%96%99-fa43bd73909d) ![image](https://hackmd.io/_uploads/rkOLiToLT.png) 上方圖片提到的,input的name attribute,在傳送資料時會變成資料的key-value pair,而如果我們想讀取它,就是利用req.body取得這對key-value。 ![image](https://hackmd.io/_uploads/ryNDsasLp.png) 老師這裡實作,Add to cart這個按鈕也能有POST request的方法,就是一樣建立form表單,只是將input給hidden起來。 :::success 補充! 若method使用POST,則可以透過req.body物件中取input的name,來獲得input的value。 例如上方input name為productId,若我們想獲得input value(即商品的id編號),則可以透過`req.body.productId` ::: ```javascript! <%- include('../includes/add-to-cart.ejs', {product: product}) %> ``` 在ejs中,可以用`{}`來裝一些local variable,讓那些local variable可以傳至其他ejs檔案中使用。 **** ## 9-123. Adding a Cart Model * **原先的code:** ```javascript! cart.totalPrice = cart.totalPrice + productPrice; ``` 但會造成相加的時候,是以String的特興趣相加,例如說一個物品標價300,則照上方code去相加兩個相同物品的標價,會變成"300300",而非我們希望的600。(如下所示) ![2023-12-17 15-46-07 的螢幕擷圖](https://hackmd.io/_uploads/ByLU_mh86.png) * **修正後的code:** 因此我們只要做一件事情,就是在`productPrice`前方加上一個加號,可以將型態轉成數字。這個加號叫做unary plus,可以參考[MDN的介紹](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Unary_plus)。 ![2023-12-17 15-58-22 的螢幕擷圖](https://hackmd.io/_uploads/H1G4cX28a.png) ```javascript! cart.totalPrice = cart.totalPrice + +productPrice; ``` 如下所示,就成功以數字來相加兩個商品的價錢了。 ![2023-12-17 15-57-47 的螢幕擷圖](https://hackmd.io/_uploads/SJRWcQhL6.png) **** ## 9-124. Using Query Params > 參考資料:[Express官方文件_req.query](https://expressjs.com/zh-tw/api.html#req.query) > ![2023-12-17 16-34-47 的螢幕擷圖](https://hackmd.io/_uploads/rk_t7EhLp.png) query指的網址中?(問號)之後的那串字串,而req.query是一個物件,用來收集所有route中的query字串。 :::info req.query跟[9-119](https://hackmd.io/@noz915/rJ8_M0cLp)的req.params用法頗像的。 差別在於: `>` req.query抓取的是URL中的query(即問號之後的字串) ``` Request URL: http://......?edit=true&title=new req.query: { "edit": "true", "title": "new" } ``` `>` req.params抓取的是URL中的route parameters(路由參數) ![2023-12-16 16-57-05 的螢幕擷圖](https://hackmd.io/_uploads/B1UdLJjLa.png) 再額外複習一個!可參考[19-122](https://hackmd.io/@noz915/rJ8_M0cLp#9-122-Passing-Data-with-POST-Requests) `>` req.body抓取的是input中的name attribute,在傳送表單時,會成為資料的一組key-value pair。 ::: ```! [註] 上方藍色區塊中req.query的部份,"edit": "true"要注意只能用"true",不能用true,這是為了確保"true"能一直以String的身份存在。 ``` ****