使用Vue CLI與Vuex建立應用程式 - 2

by vivid 2. 十月 2019 01:22

.NET Magazine國際中文電子雜誌
作 者:許薰尹
審 稿:張智凱
文章編號: N191021201
出刊日期: 2019/10/2

本篇文章延續《使用Vue CLI與Vuex建立應用程式》一文的說明,利用REST API設計留言應用程式的新增、刪除、修改留言功能。

 

指定遠端資料來源

JSONPlaceholder網站提供偽線上REST API服務,以提供給應用程式開發、測試時使用,您不需要自行建立一個真實的REST API,節省開發的時間。其官網在以下網址:「https://jsonplaceholder.typicode.com/」。後續的留言版範例程式將改成使用以下網址提供的留言資料:

https://jsonplaceholder.typicode.com/comments

由於網站提供的comment測試資料共有500筆,我們可以在網址後方利用查詢字串加上「_limit」,限定只有回傳10筆資料供測試使用:

https://jsonplaceholder.typicode.com/comments?_limit=10

在專案之中,我們需要撰寫veux的Actions來送出AJAX請求,從遠端JSONPlaceholder REST API服務取得comment資料。先修改專案中的「state.js」檔案,移除掉靜態資料,讓「comments」屬性的值是一個空的陣列:

src\store\state.js

export default {
  comments: []
}

Actions可以以同步或非同步的方式來執行,因為Actions可能需要花費較冗長的時間才能完成,所以不要直接透過vuex中的Actions程式碼來修改狀態,要異動狀態應該要透過Mutations。

修改「actions.js」檔案,定義一個「getCommentsAction」函式,利用「axios」插件來送出AJAX請求,因此在檔案中第一行程式先利用「import」關鍵字匯入「axios」插件,在「getCommentsAction」函式之中,叫用「axios.get」函式,從JSONPlaceholder REST API下載10筆資料。接著叫用「commit」函式,它將會叫用「mutations.js」中的「getComments」函式來更新狀態(state):

src\store\actions.js

 

import axios from 'axios'
export default {
  async getCommentsAction({ commit }) {
    const response = await axios.get(
      'https://jsonplaceholder.typicode.com/comments?_limit=10'
    )
    commit('getComments', response.data);
  }
}


 

修改「mutations.js」檔案,加入「getComments」函式,此函式接收兩個參數,第一個參數代表state;第二個參數則是「axios」取回的comments資料,我們在「getComments」函式中,透過Mutations來更新狀態:

src\store\mutations.js

export default {

  getComments: (state, comments) => (state.comments = comments)

}

修改「Comments.vue」檔案,我們註冊組件的「created」事件,在組件建立時,叫用「getCommentsAction」函式以透過AJAX來取得遠端來源來源 資料:

Comments.vue

<template>
  <div>
    <h3>Comments</h3>
    <b-list-group>
      <b-list-group-item v-for="comment in getAllComments" v-bind:key="comment.id">{{comment.email}}</b-list-group-item>
    </b-list-group>
  </div>
</template>

<script>
import { mapGetters, mapActions } from "vuex";

export default {
  name: "Comments",
  methods: {
    ...mapActions(["getCommentsAction"])
  },
  computed: {
    ...mapGetters(["getAllComments"])
  },
  created() {
    this.getCommentsAction();
  }
};
</script>

<style scoped>
.list-group-item {
  color: blueviolet;
}
</style>

目前應用程式首頁的執行結果參考如下,你可以看到從JSONPlaceholder下載的10筆Comment資料中的電子郵件資訊:

clip_image002

圖 1:取得遠端資料來源資料。

由於在組件之中可能需要叫用多個Action,也可能有多個計算屬性要做對應,我們可以利用spread(...)運算子,改寫「Comments.vue」程式如下:

Comments.vue

<template>
  <div>
    <h3>Comments</h3>
    <b-list-group>
      <b-list-group-item v-for="comment in getAllComments" v-bind:key="comment.id">{{comment.email}}</b-list-group-item>
    </b-list-group>
  </div>
</template>

<script>
import { mapGetters, mapActions } from "vuex";

export default {
  name: "Comments",
  methods: {
    ...mapActions(["getCommentsAction"])
  },
  computed: {
    ...mapGetters(["getAllComments"])
  },
  created() {
    this.getCommentsAction();
  }
};
</script>

<style scoped>
.list-group-item {
  color: blueviolet;
}
</style>

 

新增Comment資料

接下來我們要來設計新增留言的功能。在「components」資料夾加入「AddComment.vue」檔案,然後加入以下程式碼,先為組件加入一個<h3>標題:

AddComment.vue

 

<template>
  <h3> Add Comment </h3>
</template>

<script>
export default {

}
</script>

<style>

</style>

 

修改「App.vue」檔案,利用「import」關鍵字匯入並註冊「AddComment.vue」組件,然後在<template>樣版中,<h4>標題下方使用「<AddComment/>」標籤插入「AddComment.vue」組件:

App.vue

<template>
  <div class="container" id="app">
    <div class="heading">
      <h1>Comments App</h1>
      <h4>Let me hear your voices.</h4>
      <AddComment/>
      <Comments/>
    </div>
  </div>
</template>

<script>
import Comments from "./components/Comments.vue";
import AddComment from "./components/AddComment.vue";

export default {
  name: "app",
  components: {
    Comments,
    AddComment
  }
};
</script>

<style>
#app {
  background-color: rgb(92, 64, 132);
  padding: 50px;
  color: rgb(255, 255, 255);
}
</style>

 

目前應用程式首頁的執行結果參考如下:

clip_image004

圖 2:加入「AddComment」功能。

修改「actions.js」檔案,設計一個「addCommentAction」函式來新增留言資料,函式中利用「axios」插件的「post」函式送出一個AJAX請求到REST API,並將要新增的留言包裝成「comment」物件傳入「post」函式的第二個參數,完成後再透過「commit」函式以叫用「mutations.js」中的「insertComment」函式來更新狀態:

src\store\actions.js

import axios from 'axios'
export default {
  async getCommentsAction({ commit }) {
    const response = await axios.get(
      'https://jsonplaceholder.typicode.com/comments?_limit=10'
    )
    commit('getComments', response.data)
  },
  async addCommentAction({ commit }, comment) {
    const response = await axios.post(
      'https://jsonplaceholder.typicode.com/comments', comment
    )
    commit('insertComment', response.data)
  }
}

 

修改「mutations.js」檔案,加入「insertComment」函式程式碼,將新增的留言加入「state.comments」之中:

src\store\mutations.js

export default {
  getComments: (state, comments) => (state.comments = comments),
  insertComment: (state, comment) => state.comments.unshift(comment)
}

 

 

留言所需的表單畫面,可以參考「https://bootstrap-vue.js.org/docs/components/form」文件中的標籤,修改「AddComment.vue」檔案,加入<b-form>表單來收集使用者輸入的留言資訊。範例中利用「@submit.prevent="onSubmit"」註冊表單的「submit」事件,在表單提交後,執行「onSubmit」函式,而函式中則叫用「addCommentAction」函式,將表單資料送到REST API做新增的處理:

AddComment.vue

<template>
  <div>
    <h3>Add Comment</h3>
    <b-form @submit.prevent="onSubmit">
      <b-form-group
        id="input-group-1"
        label="Email address:"
        label-for="input-1"
        description="We'll never share your email with anyone else."
      >
        <b-form-input
          id="input-1"
          v-model="form.email"
          type="email"
          required
          placeholder="Enter email"
        ></b-form-input>
      </b-form-group>

      <b-form-group id="input-group-2" label="Your Name:" label-for="input-2">
        <b-form-input id="input-2" v-model="form.name" required placeholder="Enter name"></b-form-input>
      </b-form-group>

      <b-form-group id="input-group-3" label="Body" label-for="input-2">
        <b-form-input id="input-2" v-model="form.body" required placeholder="Enter body"></b-form-input>
      </b-form-group>

      <b-button type="submit" variant="primary">Submit</b-button>
    </b-form>
  </div>
</template>

<script>
import { mapActions } from "vuex"

export default {
  name: "AddComment",
  methods: {
    ...mapActions(["addCommentAction"]),
    onSubmit () {
      this.addCommentAction(this.form)
      this.form = {
        email: '',
        name: '',
        body: ''
      }
    }
  },
  data() {
    return {
      form: {
        email: "",
        name: "",
        body: ""
      }
    }
  }
}
</script>

<style>
</style>

 

下一個步驟則是修改「Comments.vue」檔案,利用<b-list-group>與<b-list-group-item>標籤來顯示詳細的留言者之「email」、「name」與「body」資訊:

Comments.vue

<template>
  <div>
    <h3>Comments</h3>
    <b-list-group>
      <b-list-group-item v-for="comment in getAllComments" v-bind:key="comment.id">
        <strong> Email : </strong>  {{comment.email}} <br/>
        <strong> Name : </strong> {{comment.name}} <br/>
        <strong> Body : </strong> {{comment.body}} <br/>
        </b-list-group-item>
    </b-list-group>
  </div>
</template>

<script>
import { mapGetters, mapActions } from "vuex"

export default {
  name: "Comments",
  methods: {
    ...mapActions(["getCommentsAction"])
  },
  computed: {
    ...mapGetters(["getAllComments"])
  },
  created() {
    this.getCommentsAction();
  }
};
</script>

<style scoped>
.list-group-item {
  color: blueviolet;
}
</style>

 

目前應用程式首頁的執行結果參考如下:

clip_image006

圖 3:新增留言畫面。

在網頁中「Add Comment」區段輸入留言資料,按下Submit後,新增的留言將會出現在下方清單,表單上文字方塊的內容將會被清空回到預設狀態:

clip_image008

圖 4:顯示新增的留言資訊。

若從瀏覽器除錯視窗檢視REST API的回應,你可以看到取得的伺服端回傳之最新新增的Comment資料,以及id編號,請參考下圖所示:

clip_image010

圖 5:檢視REST API的回應。

因為JSONPlaceholder 是一個用於測試的REST API服務,因此當你再度提交資料到JSONPlaceholder API,從瀏覽器的主控台(Console)會看到以下錯誤訊息:

clip_image012

圖 6:僞REST API服務回應。

新增資料永遠都會得到最新Comment id編號為「501」,而理論上id是不可以重複的,未來連接到真實的REST API服務就不會有這個問題,目前可以將這個錯誤忽略掉。未來應用程式之中若有這個問題的話,應該是REST API的設計有問題。

 

設計刪除功能

下一個步驟我們要為應用程式加入留言刪除的功能。修改「Comments.vue」檔案,使用「<div class="del"></div>」標籤加上刪除圖示,然後在<style>區段定義刪除圖示所需的CSS樣式:

Comments.vue

<template>
  <div>
    <h3>Comments</h3>
    <b-list-group>
      <b-list-group-item v-for="comment in getAllComments" v-bind:key="comment.id">
        <div class="del"></div>
        <strong> Email : </strong>  {{comment.email}} <br/>
        <strong> Name : </strong> {{comment.name}} <br/>
        <strong> Body : </strong> {{comment.body}} <br/>
      </b-list-group-item>
    </b-list-group>
  </div>
</template>

<script>
import { mapGetters, mapActions } from "vuex"

export default {
  name: "Comments",
  methods: {
    ...mapActions(["getCommentsAction"])
  },
  computed: {
    ...mapGetters(["getAllComments"])
  },
  created() {
    this.getCommentsAction();
  }
};
</script>

<style scoped>
.list-group-item {
  color: blueviolet;
}
.del {
  height: 50px;
  width: 50px;
  right : 30px;
  background-color: #FA6900;
  border-radius: 5px;
  position: absolute;
}
.del:after {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  content: "\d7";
  font-size: 50px;
  color: #FFF;
  line-height: 40px;
  text-align: center;
}
</style>

 

目前應用程式首頁的執行結果參考如下,每一筆Comment資料後方,都會加上一個「X」圖示:

clip_image014

圖 7:加上刪除圖示。

叫用REST API刪除資料

修改「actions.js」檔案,加入「removeCommentAction」函式,叫用「axios.delete」函式送出刪除資料的AJAX請求,並傳送「id」參數指明要刪除的Comment留言編號,完成後透過「commit」函式來叫用Mutations的「deleteComment」函式以更新狀態:

src\store\actions.js

import axios from 'axios'
export default {
  async getCommentsAction({ commit }) {
    const response = await axios.get(
      'https://jsonplaceholder.typicode.com/comments?_limit=10'
    )
    commit('getComments', response.data)
  },
  async addCommentAction({ commit }, comment) {
    const response = await axios.post(
      'https://jsonplaceholder.typicode.com/comments', comment
    )
    commit('insertComment', response.data)
  },
  async removeCommentAction({ commit }, id) {
    await axios.delete(`https://jsonplaceholder.typicode.com/comments/${id}`);
    commit('deleteComment', id);
  }
}

 

修改「mutations.js」檔案,加入「deleteComment」函式,從「state.comments」之中移除id相符的comment留言資料:

src\store\mutations.js

export default {
  getComments: (state, comments) => (state.comments = comments),
  insertComment: (state, comment) => state.comments.unshift(comment),
  deleteComment: (state, id) => state.comments = state.comments.filter(c => c.id !== id)
}

 

修改「Comments.vue」檔案,註冊刪除按鈕的「click」事件,在事件觸發時,叫用「removeCommentAction」函式,傳入要刪除的「comment.id」當參數,以送出刪除的請求到REST API:

Comments.vue

<template>
  <div>
    <h3>Comments</h3>
    <b-list-group>
      <b-list-group-item v-for="comment in getAllComments" v-bind:key="comment.id">
        <div class="del" @click="removeCommentAction(comment.id)"></div>
        <strong> Email : </strong>  {{comment.email}} <br/>
        <strong> Name : </strong> {{comment.name}} <br/>
        <strong> Body : </strong> {{comment.body}} <br/>
      </b-list-group-item>
    </b-list-group>
  </div>
</template>

<script>
import { mapGetters, mapActions } from "vuex"

export default {
  name: "Comments",
  methods: {
    ...mapActions(["getCommentsAction" ,"removeCommentAction"])
  },
  computed: {
    ...mapGetters(["getAllComments"])
  },
  created() {
    this.getCommentsAction();
  }
};
</script>

<style scoped>
.list-group-item {
  color: blueviolet;
}
.del {
  height: 50px;
  width: 50px;
  right : 30px;
  background-color: #FA6900;
  border-radius: 5px;
  position: absolute;
}
.del:after {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  content: "\d7";
  font-size: 50px;
  color: #FFF;
  line-height: 40px;
  text-align: center;
}
</style>

 

目前應用程式首頁的執行結果參考如下,只要點選刪除小圖示,就會將此筆資料刪除:

clip_image016

圖 8:資料刪除。

使用「vue-router」插件啟用路由

在留言應用程式中,需要有一個「About」頁面,顯示應用程式資訊,而且還需要有一個編輯留言的頁面,讓我們修改原有留言的內容。我們需要路由系統來協助切換到不同的頁面。「vue-router」插件可以幫助我們完成路由的處理。我們需要先在專案之中安裝「vue-router」插件(plugin),以啟用路由功能,先切換到命令提示字元,在專案根目錄,輸入以下指令:

npm install vue-router

接著修改「main.js」檔案,使用「import」關鍵字匯入「vue-router」,並在使用「new」關鍵字建立Vue實例時,直接注入「vue-router」:

main.js

import Vue from 'vue'
import BootstrapVue from 'bootstrap-vue'

import App from './App.vue'

import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap-vue/dist/bootstrap-vue.css'

import router from './router'
import store from './store'

Vue.config.productionTip = false
Vue.use(BootstrapVue)
new Vue({
  router,
  store,
  render: h => h(App),
}).$mount('#app')


 

接著我們要將原來在「App.vue」要顯示的內容搬到「Home.vue」組件中,然後修改「App.vue」檔案利用<router-link>定義「Home」與「About」兩個連結,<router-link>實際上是一個組件(Component)。修改「App.vue」檔案程式碼如下:

App.vue

<template>
  <div class="container" id="app">
     <div id="nav">
      <router-link to="/">Home</router-link> |
      <router-link to="/about">About</router-link>
    </div>
    <b-container>
      <router-view/>
    </b-container>
  </div>
</template>

<script>
export default {
  name: "app",
  components: {
  }
}
</script>

<style>
#app {
  background-color: rgb(92, 64, 132);
  padding: 50px;
  color: rgb(255, 255, 255);
}
</style>

 

<router-view/> 標籤所在的位置是一個定位點,代表未來透過路由執行的「Home.vue」、「About.vue」組件標籤所要插入的位置。

接著在「components」資料夾中加入「About.vue」檔案, 並在檔案中加入以下內容,隨意在標題下方加入一些亂數假文:

components\About.vue

<template>
  <div>
    <h1> About</h1>
    Lorem ipsum dolor sit amet consectetur adipisicing elit. Asperiores consectetur quo consequuntur beatae sapiente illum atque quia aut nulla explicabo.
  </div>
</template>

<script>
export default {

}
</script>

<style>

</style>


 

在「components」資料夾中加入「Home.vue」檔案,將先前在「App.vue」檔案中的內容加入,注意,我們修改了「import」那行程式碼,程式之中使用到了「@」符號,它對應到「src」資料夾:

components\Home.vue

<template>
  <div class="heading">
    <h1>Comments App</h1>
    <h4>Let me hear your voices.</h4>
    <AddComment/>
    <Comments/>
  </div>
</template>

<script>
import Comments from "@/components/Comments.vue"
import AddComment from "@/components/AddComment.vue"
export default {
  name: "home",
  components: {
    Comments,
    AddComment
  }
};
</script>

<style>
</style>

 

在「src」資料夾之中加入「router.js」檔案,建立並匯出「Router」物件,在「routes」屬性使用陣列來定義兩個路由,「/」路徑會顯示「Home.vue」頁面;「/About」路徑將顯示「About.vue」頁面,而「name」是選擇性的:

src\router.js

import Vue from 'vue'
import Router from 'vue-router'
import Home from './components/Home.vue'
import About from './components/About.vue'

Vue.use(Router)

export default new Router({
  mode: 'history',
  base: process.env.BASE_URL,
  routes: [
    {
      path: '/',
      name: 'home',
      component: Home
    },
    {
      path: '/About',
      name: 'about',
      component: About
    }
  ]
})

 

目前應用程式首頁的執行結果參考如下,網頁上方顯示「Home」、「About」兩個連結:

clip_image018

圖 9:使用路由系統切換到首頁、關於畫面。

點選「About」連結將切換到「About(關於)」頁面,請參考下圖所示:

clip_image020

圖 10:使用路由系統切換到「About(關於)」頁面。

設計選單樣式

預設選單的樣式較為單調,搭配Bootstrap Vue可以美化其外觀,參考官網文件的說明:「https://bootstrap-vue.js.org/docs/components/nav/#navs」,我們改用<b-nav>與<b-nav-item>標籤來顯示選單,並利用「isActive」變數來判斷哪一個選項要套用「active」attribute:

App.vue

<template>
  <div class="container" id="app">
    <b-nav tabs fill id="nav">
      <b-nav-item id="navhome" @click="isActive=true" to="/" :active="isActive">Home</b-nav-item>
      <b-nav-item id="navabout" @click="isActive=false" to="/About" :active="!isActive">About</b-nav-item>
    </b-nav>
    <b-container>
      <router-view />
    </b-container>
  </div>
</template>

<script>
export default {
  name: "app",
  components: {},
  data() {
    return {
      isActive: true
    }
  }
}
</script>

<style>
#app {
  background-color: rgb(92, 64, 132);
  padding: 50px;
  color: rgb(255, 255, 255);
}
</style>

 

目前應用程式首頁的執行結果參考如下,預設「Home」的狀態是選取的(Active),因此背景顏色套用白色:

clip_image022

圖 11:套用Bootstrap Vue選單樣式。

若選取「About」連結,則「About」選項的背景顏色就會套用白色,請參考下圖所示:

clip_image024

圖 12::套用Bootstrap Vue選單樣式。

設計資料修改功能

最後我們要完成留言資料修改功能,使用者可以在首頁選取其中一筆留言資料,並利用路由切換到編輯畫面(EditComment.vue檔案),例如,若要修改「id」為「1」的資料,我們希望路由看起來為:

http://localhost:8080/edit/1

若要修改「id」為「2」的資料,我們希望路由看起來為:

http://localhost:8080/edit/2

我們需要動態路由來設定「id」。此外編輯畫面(EditComment.vue)要帶出目前資料的明細,以讓使用者修改資料,完成後將異動後的資料送到REST API,以更新後端資料。

修改「router.js」檔案,註冊動態路由,在「path」區塊中,我們使用到「:id」參數:

router.js

 

import Vue from 'vue'
import Router from 'vue-router'
import Home from './components/Home.vue'
import About from './components/About.vue'
import EditComment from './components/EditComment.vue'

Vue.use(Router)

export default new Router({
  mode: 'history',
  base: process.env.BASE_URL,
  routes: [
    {
      path: '/',
      name: 'home',
      component: Home
    },
    {
      path: '/about',
      name: 'about',
      component: About
    },
    {
      path: '/edit/:id',
      name: 'editComment',
      component: EditComment
    }
  ]
})

 

在「components」資料夾中加入「EditComment.vue」檔案,然後加入以下程式碼,利用「this.$route.params.id」從路由資料中,取出「id」參數的值:

components\EditComment.vue

 

<template>
  <div>
    <h3>Edit Comment</h3>
    {{this.$route.params.id}}
  </div>
</template>

<script>
export default {

}
</script>

<style>

</style>


目前應用程式的首頁執行結果參考如下,在瀏覽器輸入以下URL:

http://localhost:8080/edit/1

將顯示「EditComment.vue」頁面,以及路由「id」參數資料,請參考下圖所示:clip_image026

圖 13:存取路由參數。

修改「EditComment.vue」檔案,加入<b-form>標籤,由於資料修改通常不允許修改識別資料的「id」值,因此在範例中顯示「id」的文字方塊上,套用「disabled」Attribute。當表單提交之後,會叫用「editCommentAction」函式,送出AJAX請求到REST API,然後利用「this.$router.push("/")」,回到首頁:

components\EditComment.vue

<template>
  <div>
    <h3>Edit Comment</h3>
    <!-- {{this.$route.params.id}} -->
    <b-form @submit.prevent="onSubmit">
      <b-form-group id="input-group-1" label="id :" label-for="input-1">
        <b-form-input id="input-1" v-model="form.id" type="text" disabled></b-form-input>
      </b-form-group>
      <b-form-group
        id="input-group-1"
        label="Email address:"
        label-for="input-1"
        description="We'll never share your email with anyone else."
      >
        <b-form-input
          id="input-1"
          v-model="form.email"
          type="email"
          required
          placeholder="Enter email"
        ></b-form-input>
      </b-form-group>

      <b-form-group id="input-group-2" label="Your Name:" label-for="input-2">
        <b-form-input id="input-2" v-model="form.name" required placeholder="Enter name"></b-form-input>
      </b-form-group>

      <b-form-group id="input-group-3" label="Body" label-for="input-2">
        <b-form-input id="input-2" v-model="form.body" required placeholder="Enter body"></b-form-input>
      </b-form-group>

      <b-button type="submit" variant="primary">Submit</b-button>
    </b-form>
  </div>
</template>

<script>
import { mapActions, mapState } from "vuex"

export default {
  name: "EditComment",
  methods: {
    ...mapActions(["editCommentAction"]),
    onSubmit() {
      this.editCommentAction(this.form)
      this.$router.push("/")
    }
  },
  data() {
    return {
      form: {}
    };
  },
  computed: {
    ...mapState(["comments"])
  },
  mounted() {
    const rid = Number.parseInt(this.$route.params.id),
      ar = this.comments,
      comment = ar.find(c => c.id == rid)
    this.form = comment
  }
}
</script>
<style>

</style>

 

修改「Comments.vue」檔案,加入<router-link>標籤,並根據comment的「id」值來組出「to」屬性的路徑。此外我們修改了「created」函式,不要每一次執行首頁時,都從REST API下載最新資料,如此異動資料時將會送兩個請求到REST API),一個put請求修改資料;一個get請求取回最新資料。這種作法較無效率,因此我們修改「created」函式程式碼,判斷「this.getAllComments.length」的值是否為0,若不為0則表示用戶端已有資料,所以只需送出一個「put」請求變更資料,然後手動更新用戶端的資料,不需要再重REST API取回資料:

Comments.vue

<template>
  <div>
    <h3>Comments</h3>
    <b-list-group>
      <b-list-group-item v-for="comment in getAllComments" v-bind:key="comment.id">
        <div class="del" @click="removeCommentAction(comment.id)"></div>
        <router-link class="edit" :to="`/edit/${comment.id}`"></router-link>
        <strong>Email :</strong>
        {{comment.email}}
        <br />
        <strong>Name :</strong>
        {{comment.name}}
        <br />
        <strong>Body :</strong>
        {{comment.body}}
        <br />
      </b-list-group-item>
    </b-list-group>
  </div>
</template>

<script>
import { mapGetters, mapActions } from "vuex"

export default {
  name: "Comments",
  methods: {
    ...mapActions(["getCommentsAction", "removeCommentAction"])
  },
  computed: {
    ...mapGetters(["getAllComments"])
  },
  created() {
    if(this.getAllComments.length <= 0)
    {
      this.getCommentsAction()
    }
  }
}
</script>

<style scoped>
.list-group-item {
  color: blueviolet;
}
.edit {
  height: 50px;
  width: 50px;
  right: 90px;
  background-color: #fa6900;
  border-radius: 5px;
  position: absolute;
}
.edit:after {
  position: absolute;
  top: 10px;
  bottom: 0;
  left: 0;
  right: 0;
  content: "\0395";
  font-size: 30px;
  color: #fff;
  line-height: 30px;
  text-align: center;
}
.del {
  height: 50px;
  width: 50px;
  right: 30px;
  background-color: #fa6900;
  border-radius: 5px;
  position: absolute;
}
.del:after {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  content: "\d7";
  font-size: 50px;
  color: #fff;
  line-height: 40px;
  text-align: center;
}
</style>

 

修改「actions.js」檔案,加入「editCommentAction」函式,利用「axios」插件送出「put」請求到REST API進行資料修改作業:

src\store\actions.js

 

import axios from 'axios'
export default {
  async getCommentsAction({ commit }) {
    const response = await axios.get(
      'https://jsonplaceholder.typicode.com/comments?_limit=10'
    )
    commit('getComments', response.data)
  },
  async addCommentAction({ commit }, comment) {
    const response = await axios.post(
      'https://jsonplaceholder.typicode.com/comments', comment
    )
    commit('insertComment', response.data)
  },
  async removeCommentAction({ commit }, id) {
    await axios.delete(`https://jsonplaceholder.typicode.com/comments/${id}`);
    commit('deleteComment', id);
  },
  async editCommentAction({ commit }, comment) {
    const response = await axios.put(
      `https://jsonplaceholder.typicode.com/comments/${comment.id}`,
      comment
    );
    commit('updateComment', response.data)
  }
}

 

修改「mutations.js」檔案,更新狀態內容,將store中「id」相符的comment物件代換掉:

src\store\mutations.js

export default {
  getComments: (state, comments) => (state.comments = comments),
  insertComment: (state, comment) => state.comments.unshift(comment),
  deleteComment: (state, id) => state.comments = state.comments.filter(c => c.id !== id),
  updateComment: (state, comment) => {
    const index = state.comments.findIndex(c => c.id === comment.id)
    if (index !== -1) {
      state.comments.splice(index, 1, comment)
    }
  }
}

 

目前應用程式的執行結果參考如下,每一筆留言資料右方有一個「E」按鈕:

clip_image028

圖 14:編輯資料。

點選「E」按鈕便將這筆資料帶入編輯畫面,請參考下圖所示:

clip_image030

圖 15:編輯選取資料。

修改完資料,按下「submit」按鈕,便會更新後端資料,然後回到首頁,請參考下圖所示:

clip_image032

圖 16:完成更新。

Tags:

.NET Magazine國際中文電子雜誌 | JavaScript | 許薰尹Vivid Hsu

新增評論




  Country flag
biuquote
  • 評論
  • 線上預覽
Loading






NET Magazine國際中文電子雜誌

NET Magazine國際中文電子版雜誌,由恆逸資訊創立於2000,自發刊日起迄今已發行超過500篇.NET相關技術文章,擁有超過40000名註冊讀者群。NET Magazine國際中文電子版雜誌希望藉於電子雜誌與NET Developer達到共同學習與技術新知分享,歡迎每一位對.NET 技術有興趣的朋友們多多支持本雜誌,讓作者群們可以有持續性的動力繼續爬文。<請加入免費訂閱>

月分類Month List