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

by vivid 18. 九月 2019 08:57

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

本系列文章將要介紹如何透過Vue CLI 3.x版來快速的建立一個Vue專案,並了解專案中相關的檔案用途,以設計一個小型的留言應用程式,可以新增、刪除、修改留言。

Vue CLI是命令列介面(Command Line Interface)的縮寫,提供一個完整的開發環境讓你能夠更容易撰寫Vue應用程式,例如讓你選擇要使用的其它程式庫(Library),並自動安裝到專案。Vue CLI自動會設定透過Webpack來打包與壓縮JavaScript程式碼、CSS檔案,以便於部署。此外也在專案中設置webpack-dev-server,用於開發階段進行測試,只要程式碼有變動,當程式儲存時,便自動同步到瀏覽器,將程式執行的結果顯示在瀏覽器上。

安裝@vue/cli

要使用Vue CLI之前,首先任務是先進行安裝的動作。可利用「npm」來下載「@vue/cli」,在命令提示字元輸入以下指令:

npm install -g @vue/cli

安裝完成後,Vue版本可以利用以下指令來查詢:

vue --version

這個命令執行結果,請參考下圖所示:

clip_image002

圖 1:檢視安裝版本。

建立專案

建立專案的方式有兩種,第一種是直接在命令提示字元下指令,另一種方式是透過 Vue UI,可以利用圖型介面來操作。以下是命令提示字元下指令的作法,參考以下語法,指定要建立一個新的專案,資料夾名稱便是專案的名稱:

vue create 資料夾名稱

例如,在命令提示視窗輸入使用以下指令,將專案命為「mycomment」後按下「Enter」鍵:

vue create mycomment

輸入指令之後,接下來會出現對話,詢問是否在目前資料夾建立專案,回答「y」,然後按下「Enter」鍵,請參考下圖所示:

clip_image004

圖 2:建立專案對話。

下一個對話會詢問是否使用預設的配置(preset) ,或者要手動進行設定,我們可以使用鍵盤的上、下鍵來進行選擇。為了簡單起見,目前先選擇使用預設的設定,加裝babel、eslint 兩個插件(plugin)後,按下「Enter」鍵,請參考下圖所示:

clip_image006

圖 3:選擇配置(preset)。

接著便會開始安裝相依插件(Plugin),這需要花費一點時間完成,請參考下圖所示:

clip_image008

圖 4:安裝相依插件。

安裝完成之後,將會看到以下訊息,若顯示以下關於git的相關訊息,可以先按下「CTRL + C」組合鍵取消批次作業,然後按下「y」跳出批次作業,請參考下圖所示(或者直接按下Enter鍵跳出)這樣專案就建立完成了:

clip_image010

圖 5:取消批次作業。

依照命令提示字元視窗最後印出的指示,我們在命令提示視窗輸入以下指令,使用「cd」切換到「mycomment」所在資料夾:

cd mycomment

在命令提示視窗輸入以下指令,啟動開發階段的webpack-dev-server網站伺服器,並執行網站:

npm run serve

開發階段的網站伺服器會動態賦予網站一個埠號,以本例來說,接聽在「8081」埠,請參考下圖所示:

clip_image012

圖 6:執行專案。

開啟瀏覽器,根據上個步驟,輸入以下網址與埠號「http://localhost:8081/」就可以看到範本網站,請參考下圖所示:

clip_image014

圖 7:範本網站。

要停止執行網站,只要在命令提示字元輸入「CTRL+C」組合鍵,停止批次作業即可。接下來我們的留言版應用程式需要額外安裝一些程式庫,回到命令提示字元。

在命令提示字元視窗中,切換目前工作路徑到「mycomment」資料夾,輸入以下指令,安裝以下插件(Plugins),其中「vuex」用於狀態管理;「axios」用來執行AJAX請求;「bootstrap-vue」用來建立應用程式UI畫面與CSS樣式;「bootstrap-vue」依賴於「bootstrap」插件,因此也需要一併進行安裝:

cd mycomment

npm install vuex axios bootstrap-vue bootstrap

在命令提示視窗,切換目前工作路徑到「mycomment」資料夾,輸入以下指令,使用Visual Studio Code開發工具開啟「mycomment」專案:

cd mycomment

Code .

新建立的專案包含許多的檔案與資料夾,幾個重點了解一下:

l 「node_modules」資料夾:已安裝的插件檔案存放位置。

l 「public」資料夾:用來存放靜態資源檔案,當你建置專案時,Webpack會忽略不會處理這個資料夾中的項目。

l 「public\index.html」檔案:網站的首頁。

l 「src」資料夾:存放原始程式碼。

l 「src\assets」資料夾:存放圖片、字型檔案等等,Webpack會在建置過程中,對此資料夾中的項目做最佳化。

l 「src\components」資料夾:存放Vue應用程式中的組件(Component)檔案。

l 「main.js」檔案,為程式的進入點,用來渲染(Render)App.vue組件,以及附加到DOM物件。

l 「App.vue」檔案,主要的組件,Vue頁面進入點。

l 「babel.config.js」檔案:用來組態babel插件。

l 「package.json」檔案:描述專案安裝的相依插件。

檔案與資料夾的結構,請參考下圖所示:

clip_image016

圖 8:預設範本專案檔案結構。

Vue程式碼的進入點是「main.js」檔案,請參考以下程式列表:

 

「main.js」檔案

import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

new Vue({
  render: h => h(App),
}).$mount('#app')

你可以看到程式中使用「import」關鍵字匯入了Vue,以及「App.vue」組件。最後使用「new」關鍵字建立Vue實例(Instance),然後叫用「render」函式渲染 App (根組件),並叫用「$mount」函式附加到DOM中id為「app」的HTML項目,即「public\index.html」檔案中,「<div id="app"></div>」這個項目。

「public\index.html」檔案

<!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">
    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
    <title>mycomment</title>
  </head>
  <body>
    <noscript>
      <strong>We're sorry but mycomment doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
    </noscript>
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
</html>

專案預設使用Webpack打包專案中的程式,並將程式插入「public\index.html」檔案中,「<!-- built files will be auto injected -->」這行註解出現的位置。你可以在命令提示字元中輸入以下指令:

npm run build

這個命令執行結果,請參考下圖所示:

clip_image018

圖 9:建置專案。

專案中將會建立一個「dist」資料夾,裏頭便包含已打包、壓縮好,未來要部署的相關樣式表與JavaScript檔案,請參考下圖所示:

clip_image020

圖 10:專案建置產生的結果。

檢視「dist\index.html」檔案,Webpack將不必要的空白、換行、縮排等字元自動移除,並將打包後的JavaScript檔案內容插入「public\index.html」檔案中,「<!-- built files will be auto injected -->」這行註解出現的位置:

 

<!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"><link rel=icon href=/favicon.ico><title>mycomment</title><link href=/css/app.e2713bb0.css rel=preload as=style><link href=/js/app.277526b2.js rel=preload as=script><link href=/js/chunk-vendors.2ce01813.js rel=preload as=script><link href=/css/app.e2713bb0.css rel=stylesheet></head><body><noscript><strong>We're sorry but mycomment doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script src=/js/chunk-vendors.2ce01813.js></script><script src=/js/app.277526b2.js></script></body></html>

「chunk-vendors.2ce01813.js」檔案會包含相依插件的程式碼,而我們「main.js」檔案中的程式碼,將會放在「app.277526b2.js」檔案之中。

 

建立「Comments」 組件

我們的目標是建立一個留言程式,而組件(Componet)是建立Vue應用程式的基本單位,封裝HTML標籤、資料與存取邏輯,也是重複使用程式碼的基本單位。我們不想要在根組件之中定義所有留言程式所需的資料與函式,透過組件可以讓留言的功能更加模組化,易於重複使用。

接下來我們要在專案中建立一個單一元件檔案(Single File Component),檔名為「Comments」用來顯示留言。在「components」資料夾中,新增一個「Comments.vue」檔案,在Viual Studio Code,選取「src\components」資料夾,然後點選上方「New File」圖示,請參考下圖所示:

clip_image022

圖 11:建立一個「Comments.vue」檔案。

在程式編輯視窗中,使用程式碼片段功能,輸入「scaffold」按下「Tab」鍵,就可以產生組件樣版,請參考下圖所示:

clip_image024

圖 12:使用程式碼片段功能插入組件樣版。

提示:要使用上述的程式碼片段功能,Visual Studio Code需要先安裝「Vetur」擴充套件(Extensions),下載的網址為:「https://marketplace.visualstudio.com/items?itemName=octref.vetur」。

目前「Comments.vue」檔案將產生以下組件樣版程式碼,「style」區段用來定義元件的樣式,「template」區段用來設定組件的HTML樣板,在此要特別注意,根項目只能有一個;「script」區段則是用來撰寫封裝組件的邏輯,並利用「export default」關鍵字將組件的功能匯出:

Comments.vue

<template>
 
</template>

<script>
export default {

}
</script>

<style>

</style>


在「Comments.vue」檔案之中,先加入一個<h1>項目來顯示留言組件的標題,並且在<script>區塊中加入程式碼,利用「name」屬性,設定匯出的組件名稱為「Comments」:

Comments.vue

<template>
  <h1> Comments </h1>
</template>

<script>
export default {
  name: 'Comments'
}
</script>

<style>

</style>


修改「App.vue」檔案,讓Index.html可以顯示出「Comments」組件內容,在<script>區段之中,利用「import」關鍵字匯入我們自訂的組件「Comments.vue」;利用「components」屬性註冊要使用的組件名稱「Comments」:

App.vue

<template>
  <div id="app">
       <Comments/>
  </div>
</template>

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

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

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>


 

 

若未停止執行先前在命令提示字元下的「npm run serve」啟動開發階段網站伺服器之指令,則可以直接切換到瀏覽器,應該就可以看到網站最新首頁的內容。除了利用命令提示字元啟動開發階段網站伺服器之外,你也可以在Visual Studio Code輸入「CTRL + `」組合鍵開啟「TERMINAL」視窗,然後輸入「npm run serve」命令來啟動開發階段網站伺服器,請參考下圖所示:

clip_image026

圖 13:啟動開發階段網站伺服器。

目前應用程式首頁的內容看起來如下圖所示:

clip_image028

圖 14:顯示留言頁面。

使用Bootstrap-vue設定UI與樣式

要美化網站,設計出符合響應式網頁設計(Responsive Web Design)的需求,我們可以一些現成的前端CSS framework來設計,本文將介紹如何利用Bootstrap-vue來設定使用者介面的HTML標籤與CSS樣式。關於Bootstrap-vue的說明,可以參考官網:「https://bootstrap-vue.js.org/」。請參考下圖所示,根據官網的以下的文件「https://bootstrap-vue.js.org/docs」,參考import bootstrap-vue與css的程式碼:

clip_image030

圖 15:使用Bootstrap-vue設定UI與樣式。

接著在「main.js」檔案之中,使用「import」關鍵字匯入「bootstrap-vue」,以及相關的CSS樣式:

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'

Vue.use(BootstrapVue)

Vue.config.productionTip = false

new Vue({
  render: h => h(App),
}).$mount('#app')

 

修改「App.vue」檔案,加上以下的標題,並套用CSS樣式,注意<template>之中根項目只能有一個,接著在<style> 區段中加上自訂的樣式設定背景與前景顏色:

App.vue

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

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

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

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

 

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

clip_image032

圖 16:使用Bootstrap-vue設定首頁樣式。

狀態管理

雖然Vue組件(Component)可以透過「props」傳遞資料,不過當應用程式更為複雜時,試想一下當應用程式之中有數百個組件,當某個組件的狀態變更時,需要透過事件與「props」傳遞來同步到多個組件,這將會是一件很困難的事情。因此,你需要一個較好的狀態(State)管理機制,能夠集中管理與分享狀態資訊,讓所有的組件能夠直接存取全域的狀態。而「Vuex」便是設計給「Vue」應用程式,用於狀態管理的設計模式與程式庫,可以集中管理應用程式中所有元件都可以存取到的共享狀態資訊。詳細的「Vuex」資訊請參考官網「https://vuex.vuejs.org/」的説明。

「Vuex」實作了完整的狀態管理設計模式(State Management Pattern),以標準化的方式來異動狀態,在「Vuex」之中,狀態是「響應式(reactive)」的,當一個組件異動狀態,其它的組件都可以收到異動通知,並可自動取得最新的值。

接下來我們來看一下「Vuex」的使用方式,首先在「src\store」資料夾中建立「actions.js」、「getters.js」、「index.js」、「mutations.js」、「state.js」四個檔案,目前的專案結構看起來如下圖所示:

clip_image034

圖 17:加入「Vuex」進行狀態管理。

「index.js」檔案將會是「vuex」進入點,我們只要在「main.js」檔案加入以下「import」程式碼,「from」後方指明「store」資料夾,這樣便會直接找尋「store」資料夾中的「index.js」檔案來執行。接著使用「new」關鍵字建立「Vue」時實體時,注入「store」,這樣所有的子組件(child components)都可以存取到「store」:

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 store from './store'

Vue.config.productionTip = false

Vue.use(BootstrapVue)

new Vue({
  store,
  render: h => h(App),
}).$mount('#app')

 

修改「index.js」檔案,加入以下程式碼,「Vue.use(Vuex)」 這行程式將載入「vuex」,而「new Vuex.Store()」這行程式碼則建立store物件,此物件將包含要共享的狀態:

src\store\index.js

import Vue from 'vue'
import Vuex from 'vuex'

import state from './state'
import mutations from './mutations'
import actions from './actions'
import getters from './getters'

Vue.use(Vuex)

export default new Vuex.Store({
  state,
  mutations,
  actions,
  getters
})

而「actions.js」、「mutations.js」先暫時加入以下程式,匯出一個空的物件:

src\store\actions.js

export default {

}

src\store\mutations.js

export default {

}

接著我們可以在「state.js」檔案之中定義狀態資料(State),目前暫時使用靜態的comment物件來儲存留言資訊,檔案中匯出一個「comments」屬性,其值是一個陣列,陣列中包含「comment」物件:

src\store\state.js

export default {
  comments: [
    {
      "postId": 1,
      "id": 1,
      "name": "id labore ex et quam laborum",
      "email": "Eliseo@gardner.biz",
      "body": "laudantium enim quasi est quidem magnam voluptate ipsam eos\ntempora quo necessitatibus\ndolor quam autem quasi\nreiciendis et nam sapiente accusantium"
    },
    {
      "postId": 1,
      "id": 2,
      "name": "quo vero reiciendis velit similique earum",
      "email": "Jayne_Kuhic@sydney.com",
      "body": "est natus enim nihil est dolore omnis voluptatem numquam\net omnis occaecati quod ullam at\nvoluptatem error expedita pariatur\nnihil sint nostrum voluptatem reiciendis et"
    },
    {
      "postId": 1,
      "id": 3,
      "name": "odio adipisci rerum aut animi",
      "email": "Nikita@garfield.biz",
      "body": "quia molestiae reprehenderit quasi aspernatur\naut expedita occaecati aliquam eveniet laudantium\nomnis quibusdam delectus saepe quia accusamus maiores nam est\ncum et ducimus et vero voluptates excepturi deleniti ratione"
    },
    {
      "postId": 2,
      "id": 6,
      "name": "et fugit eligendi deleniti quidem qui sint nihil autem",
      "email": "Presley.Mueller@myrl.com",
      "body": "doloribus at sed quis culpa deserunt consectetur qui praesentium\naccusamus fugiat dicta\nvoluptatem rerum ut voluptate autem\nvoluptatem repellendus aspernatur dolorem in"
    }
  ]
}

 

為了要存取state中的資料,我們需要定義「getters」函式,在「getters.js」檔案中,加入一個「getAllComments」函式,取得「state.comments」資料:

src\store\getters.js

export default {
  getAllComments: (state) => {
    return state.comments
  }
}

參考「bootstrap-vue」官網「https://bootstrap-vue.js.org/docs/components/list-group」文件中的標籤,來修改「Comments.vue」檔案,加入以下程式碼,使用<b-list-group>與<b-list-group-item>來呈現留言資料。其中<style>開頭標籤中加上「scoped」關鍵字代表此樣式只在此組件(Component)之中生效。

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 } from "vuex"

export default {
  name: "Comments",
  computed: mapGetters(["getAllComments"])
};
</script>

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

 

在「Comments.vue」組件之中若要讀取Vuex中的狀態(State),可以透過計算屬性(Computed Properties),組件的<template>之中便可以利{{ }}語法來顯示狀態資料。因此,我們在程式中匯入「vuex」,然後定義一個計算屬性「getAllComments」,叫用「mapGetters」函式,將「getAllComments」屬性對應到「getters」的「getAllComments」函式,如此在「v-for="comment in getAllComments"」這行程式讀取「getAllComments」屬性時,就會叫用「Vuex」的「getters」之「getAllComments」函式來取得狀態資料。完成這個步驟之後,目前應用程式首頁的執行結果參考如下:

clip_image036

圖 18:顯示靜態資料。

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