# json-server 環境教學 - 打造自己的作品 ## 為什麼要安裝 postman? [POSTMAN 官網](https://www.postman.com/) 至官網直接安裝 ![](https://hackmd.io/_uploads/SyauKv8rh.png) ### 優勢 1. 各種類型的網路請求,例如 get post put patch del 2. API網址 3. 回傳的內容,例如 GET 可以取得JSON 資料 4. 方便快速測試,不用在撰寫JS,即可測試API 5. 側邊欄可以整理整合 --- ## json-server ### 安裝 [json-server GitHub](https://github.com/typicode/json-server) Install JSON Server : 需要進入終端機後(win 可用 crtl + R 輸入 cmd d) ``` npm install -g json-server ``` Create a db.json file with some data : 創建一個 db.json 的檔案 ,需要在C槽底下,範例格式如下 ``` { "posts": [ { "id": 1, "title": "json-server", "author": "typicode" } ], "comments": [ { "id": 1, "body": "some comment", "postId": 1 } ], "profile": { "name": "typicode" } } ``` Start JSON Server : 於終端機,首先需要cd使終端機進入到資料夾(圖1),輸入以下指令 (圖2),即可開啟JSON 伺服器(圖3),恭喜可以開始你的API操作了~ ``` json-server --watch db.json ``` 圖1 ![](https://hackmd.io/_uploads/H1hh2vLH2.png) 圖2 ![](https://hackmd.io/_uploads/BktR2PLS3.png) 圖3 ![](https://hackmd.io/_uploads/SJxQu2w8Bh.png) --- ## json-server 與一般常見伺服器架構差異介紹 ![](https://hackmd.io/_uploads/SyiP6wLr3.png) 一般的前端後端的做法如上圖 ``` 1. 前端瀏覽器使用API向伺服器請求 2. 伺服器再從資料庫取得資料 3. 資料庫回傳給伺服器 4. 伺服器再傳給前端瀏覽器資料 ``` ![](https://hackmd.io/_uploads/SyIURDLH3.png) json-server步驟如上圖 ``` 1. 前端瀏覽器使用API發出請求 2. json-server 使用node.js + express 架成模擬用伺服器 3. 伺服器直接從本地端只取得"一次"的 db.json,記錄在本身的記憶體中 4. 伺服器再傳給前端瀏覽器資料 ``` ![](https://hackmd.io/_uploads/rJ7cj_Lr3.png) ``` 將 API伺服器 與 網頁分開,類似於前後端分離 ``` --- ## 新增網頁,來讀取自己打造的 json-server API ![](https://hackmd.io/_uploads/rkEyCOLHn.png) json-server需要是開啟的狀態下,如果是關閉則會出現錯誤 此處範例有三個API,下圖為posts的json資料 ![](https://hackmd.io/_uploads/HyObCOLS2.png) 使用這三個API,透過AJAX向伺服器取得新增.....等等操作資料 範例程式碼如下: html ``` <h1>JSON-server 測試</h1> <button id="postApi" type="button" click="postApi()">新增</button> <button id="getApi" type="button" click="getApi()">取得</button> <script src="https://unpkg.com/axios@1.1.2/dist/axios.min.js"></script> <script src="./all.js"></script> ``` js ``` // 新增API const post = document.querySelector('#postApi') post.addEventListener('click',(e)=> { postApi() }) function postApi() { axios.post('http://localhost:3000/posts', { "title": "json-server2", "author": "typicode2" }) .then((res)=> { console.log(res); }) } //取得API const get = document.querySelector('#getApi') get.addEventListener('click',(e)=> { getApi() }) function getApi() { axios.get('http://localhost:3000/posts') .then((res)=> { console.log(res); }) } ``` --- ## db.json 架構設計 ![](https://hackmd.io/_uploads/rJL-JtLrh.png) 1. 開頭須為物件 2. 第一個物件的key值,會被視為API網址 3. 建議為陣列存放資料 (因如果替換修改資料,物件需要整筆覆蓋才可修改資料,例如profile) 4. 以物件新增存放各筆資料 如下為自己新增的API,空陣列,新增資料會為物件格式。 ``` { "apiName": [] } ``` --- ## json-server API 各種使用功能 ### Filter 篩選 以?串接 * 物件名 = 值 例如: ?title=json-server 則會篩選資料中title 是 json-server 的資料 同時搜尋各種條件,以&串接 例如: ?id=1&id=2 亦可以針對內部屬性搜尋 例如: ?author.name=typicode ``` GET /posts?title=json-server&author=typicode GET /posts?id=1&id=2 GET /comments?author.name=typicode ``` ### Full-text search 關鍵字搜尋 以?串接, * q=關鍵字內容 `GET /posts?q=internet` ### Paginate 分頁 以?串接, * _page 第幾頁 * _limit 限制一頁有幾筆資料(自動將資料做分頁) 預設是返回10筆資料 ``` GET /posts?_page=7 GET /posts?_page=7&_limit=20 ``` ### sort 排序 * _sort 依所填值為條件排序 * _order 排序方式 asc 為 低到高 (小到大) // desc為 高到低 (大到小) ``` GET /posts?_sort=views&_order=asc GET /posts/1/comments?_sort=votes&_order=asc ``` 亦可複數條件做篩選 ``` GET /posts?_sort=user,views&_order=desc,asc ``` ### Operators 區間篩選 * _gte 起始值 * _lte 終點值 `GET /posts?views_gte=10&views_lte=20` * _ne 包含值 `GET /posts?id_ne=1` * _like 過濾器 (支持正則表達式) `GET /posts?title_like=server` --- ## todolist restful API練習 ![](https://hackmd.io/_uploads/HyYeBFLH2.png) * 檔案下載 [ APIcode.zip](https://cdn.fs.teachablecdn.com/E69DnOCwQtOzndkAhrFR) * CodePen [本地端 Codepen 代辦事項練習 ](https://codepen.io/hexschool/pen/OJWRqrN?editors=1010) html ``` <input type="text" class="txt" placeholder="請輸入待辦事項"> <input type="button" class="save" value="儲存待辦"> <ul class="list"></ul> ``` js ``` const txt = document.querySelector('.txt'); const save = document.querySelector('.save'); const list = document.querySelector('.list'); let data = []; function renderData(){ let str = ''; data.forEach(function (item,index) { str+=`<li>${item.content} <input class="delete" type="button" data-num="${index}" value="刪除待辦"></li>` }) list.innerHTML = str; } // 新增待辦功能 save.addEventListener('click',function(e){ if (txt.value=="") { alert("請輸入內容"); return; } let obj = {}; obj.content = txt.value data.push(obj); renderData(); }) // 刪除待辦功能 list.addEventListener("click",function(e){ if(e.target.getAttribute("class")!=="delete"){ return; } let num = e.target.getAttribute("data-num"); console.log(num); data.splice(num,1); alert("刪除成功!"); renderData(); }) ```