前言:
本篇是紀錄Vue RESTful API的簡單學習筆記
學習的內容來自 Alex大大的 Vue 全家桶與 RESTful API 串接入門介紹
這個VUE's RESTful API系列的影片有兩部,長達七個小時,當初在YouTube上發現,Alex大大解說的方式,我可以聽得懂,就順勢入坑。
當初第一次看的時候,也是花了好幾天才把影片的範例給做完
但由於本身並不是寫前端的,只是偶爾寫一下python
所以學過的東西沒在用,很容易忘記...記得第一次看的時候是過年前
三月再回頭看,發現已經忘記...再看一次...
四月底再回頭看...發現又忘記...且之前寫的檔案也不知丟哪了...
才想到寫blog來記錄學習過程的重要...我也好久沒更新blog...
在開始貼程式碼前,總結一下這次每看必忘的學習過程...
最大的原因大概就是,我是直接學VUE,看這系列影片之前
有看過前端的教學影片, AMOS大大的 :
金魚都能懂的網頁設計入門 - 金魚都能懂了你還怕學不會嗎
But... 對JavaScript的了解,只停留在變數、迴圈、判斷式
很多東西如 dispatch、axios、promise、then、箭頭函式...等
都是在VUE的教學影片中看到...還以為這些都是VUE的特有功能...
再加上看完影片後,當下覺得可以理解影片的內容
但從沒自己找個side project練練手...加上金魚的記憶能力... XDD
anyway 要學VUE...還是得先從JavaScript開始。
複製貼上程式碼之前
1.用NPM 安裝 json-server
npm i -g json-server
2.啟動 json-server (終端機下)
json-server 你的json檔案.json
3.注意事項:
VS Code 套件 live server 的 auto-reload 會產生的坑
解決方式:請看VCR...
以下就開始複製貼上程式碼...
只有新增跟刪除資料的功能,沒有使用VUE Router跟VUEX
網頁畫面:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vue RESTful API</title>
</head>
<body>
<div id="app">
<p>
<!-- trim 去頭尾空白 -->
<input type="text" v-model.trim="input" /><a
href="javascript:;"
v-on:click="cerateHandler"
>Create</a
>
</p>
<ol>
<li v-for="(content,index) in contents">
{{content.content}} <a href="javascripts:;">Update</a>
<a href="javascript:;" v-on:click="deleteHandler(index)">Delete</a>
</li>
</ol>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue-router/3.0.1/vue-router.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vuex/3.0.1/vuex.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.js"></script>
</body>
</html>
<script>
new Vue({
el: "#app",
// ES6寫法
data: {
input: "",
contents: [],
},
methods: {
cerateHandler() {
if (!this.input) {
return false;
}
// console.log("cerateHandler on clicked", this.input);
// axios.post 塞資料到api
axios
.post("http://localhost:3000/contents", {
content: this.input,
})
.then((res) => {
// 清空輸入欄位 , 資料輸出到網頁上
// push 是陣列 新增資料的用法 (contents是陣列)
(this.input = ""), this.contents.push(res.data);
});
},
// axios 刪除功能
deleteHandler(index) {
let target = this.contents[index];
// console.log("target= ", target);
axios
.delete(http://localhost:3000/contents/${target.id}
)
.then((res) => {
this.contents.splice(index, 1);
});
},
},
mounted() {
axios.get("http://localhost:3000/contents").then((res) => {
// console.log(res.data);
this.contents = res.data;
});
},
});
</script>
接下來是完整的程式,有使用到VUE Router跟VUEX
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vue RESTful API</title>
</head>
<body>
<div id="app">
<router-view></router-view>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue-router/3.0.1/vue-router.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vuex/3.0.1/vuex.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.js"></script>
</body>
</html>
<script>
let List = {
template: `<div>
<p>
<input type="text" v-model.trim="input" /><a
href="javascript:;" v-on:click="cerateHandler"> Create </a>
</p>
<ol>
<li v-for="(item,index) in contents" :key="item.id">
{{item.content}}
<a href="javascripts:;" v-on:click="updateHandler(index)"> Update </a>
<a href="javascript:;" v-on:click="deleteHandler(index)"> Delete </a>
</li>
</ol>
</div>`,
// ES6寫法
data: function () {
return {
input: "",
// contents: [],
};
},
computed: {
contents() {
return this.$store.state.contents;
},
},
methods: {
cerateHandler() {
if (!this.input) {
return false;
}
// console.log("cerateHandler on clicked", this.input);
// axios.post 塞資料到api
axios
.post("http://localhost:3000/contents", {
content: this.input,
})
.then((res) => {
// 清空輸入欄位 , 資料輸出到網頁上
// push 是陣列 新增資料的用法 (contents是陣列)
this.input = "";
// this.contents.push(res.data);
//上面不能push資料到data 開嚴格模式會報錯 ,沒開會讓你刪沒報錯 但是不合法 要走mutation 如下
this.$store.commit("addContent", res.data);
});
},
// axios 刪除功能
deleteHandler(index) {
let target = this.contents[index];
// console.log("target= ", target);
//改成 action => mutation
// axios
// .delete(http://localhost:3000/contents/${target.id}
)
// .then((res) => {
// this.contents.splice(index, 1);
// });
// 先進 action 再進 mutation
//CONTENT_DELETE 就是給action用的
this.$store.dispatch("CONTENT_DELETE", { target });
},
// axios 更新功能
updateHandler(index) {
// console.log(this);
let target = this.contents[index];
// this.$router.push({ path: /update/${target.id}
});
// id不是亂取的 是設定 router 時 設定的 path: "/update/:id" <=這個id
//用name params寫法
this.$router.push({ name: "update", params: { id: target.id } });
// 寫法2
// this.$router.push({path:'/update/'+target.id})
},
},
mounted() {
// axios.get("http://localhost:3000/contents").then((res) => {
// // console.log(res.data);
// this.contents = res.data;
// });
},
};
let Edit = {
template: <div><p><input type="text" v-model.trim="input" /><a href="javascripts:;" v-on:click="updateHandler">Update</a></p></div>
,
data() {
return {
input: "",
};
},
computed: {
content() {
return this.$store.state.contents.find((item) => {
return item.id == this.$route.params.id;
});
},
},
methods: {
updateHandler() {
this.$store
.dispatch("CONTENT_UPDATE", {
id: this.content.id,
input: this.input,
})
.then(() => {
this.$router.push({ path: "/" });
});
},
},
mounted() {
if (!this.content) return this.$router.replace({ path: "/" });
this.input = this.content.content;
},
};
let store = new Vuex.Store({
strict: true,
state: {
contents: [],
},
mutations: {
SET_CONTENTS(state, data) {
state.contents = data;
},
addContent(state, data) {
state.contents.push(data);
},
deleteContent(state, data) {
state.contents.splice(data, 1);
},
updateContent(state, { item, input }) {
item.content = input;
},
},
actions: {
CONTENTS_READ: (context) => {
// console.log("context= ", context);
// 讀資料 要return
return axios.get("http://localhost:3000/contents").then((res) => {
context.commit("SET_CONTENTS", res.data);
});
},
CONTENT_DELETE: (context, { target }) => {
let index = context.state.contents.indexOf(target);
if (index == -1) return false;
return axios
.delete("http://localhost:3000/contents/" + target.id)
.then((res) => {
context.commit("deleteContent", index);
});
},
CONTENT_UPDATE: (context, { id, input }) => {
console.log("UPDATE");
let item = context.state.contents.find((item) => {
return item.id == id;
});
if (!item) return false;
return axios
.patch("http://localhost:3000/contents/" + item.id, {
content: input,
})
.then((res) => {
context.commit("updateContent", { item, input });
});
},
},
});
// 設定 vue router
let router = new VueRouter({
//由上往下走~有順序之分
routes: [
{
path: "/",
name: "list",
component: List,
},
{
path: "/update/:id",
name: "update",
component: Edit,
},
{
path: "*",
redirect: "/",
},
],
});
new Vue({
el: "#app",
// 掛載router ES6
router,
store,
mounted() {
// this.$store.dispatch("CONTENTS_READ");
this.$store.dispatch("CONTENTS_READ");
},
});
</script>
以上就是,這兩部影片的內容...做完這個範例,不能說就可以完全了解VUE的運作,只能有一個初步的認識...離可以自行做一個side project還有一段路要走...
Reference:
- Alex 宅幹嘛 👨💻 Vue 全家桶與 RESTful API 串接入門介紹 part1
- Alex 宅幹嘛 👨💻 Vue 全家桶與 RESTful API 串接入門介紹 part2