.NET Magazine國際中文電子雜誌
作 者:許薰尹
審 稿:張智凱
文章編號:N190520702
出刊日期: 2019/5/15
Vue.js是一個開放源碼(Open Source),漸進式框架(Progressive JavaScript Framework),用於開發互動式的網頁使用者操作介面。目前有許多類似的漸進式框架可以簡化前端網頁程式的開發動作,那麼Vue.js有什麼不同呢? Vue.js的特色是專注在使用者檢視層(View),簡單、易用,容易整合到現有的大型專案之中使用。
Vue.js是由前Google工程師尤雨溪(Evan You)發明的,目前加盟阿里巴巴Weex團隊,Vue.js第一個版本是在2014年2月問市,現在已經成為一個非常流行的前端開發框架。
Vue.js提供的特色如下:
- 輕量型的框架:輕量、且效能好。
- Vue.js專注在MVVM(Model - View - ViewModel)設計模式中的ViewModel層。
- 採用虛擬DOM(Virtual DOM),不直接操作DOM,而是建立一個以JavaScript資料結構形式存在的DOM複本,直接對JavaScript資料結構進行異動。所進行的異動稍後會自動更新到真正的DOM,如此將可進行最佳化以提升效能。
- 提供資料繫結(Data Binding)能力:此功能可以將值關聯到指定的HTML標籤或Attribute,以變更顯示資料或套用樣式。
- 元件(Component):可以利用元件建立自訂的項目,便可以在HTML網頁中重複地使用。
- 事件處理:透過簡單的HTML Attribute註冊DOM事件。
- 動畫效果:可以在DOM物件項目新增、修改時,為HTML項目設定動畫效果。
- 計算屬性(Computed Properties):可以接聽HTML UI介面中項目的異動,不需要撰寫額外的程式碼,可以進行一些必要的運算。
- 樣板(Templates):提供以HTML為基礎的樣版,以便將DOM物件繫結到Vue實體(Instance)資料。
- 指示詞(Directives):內建許多「v-」開頭的指示詞,用來進行程式邏輯的判斷。
- 監看程式(Watchers):自動監看資料是否有異動。
- 路由(Routing):用來導覽至其它網頁。
在這篇文章中,將要介紹Vue.js基本使用,從安裝開發環境,到使用Vue.js元件。
開發環境安裝與設定
最簡單的安裝方式便是到官網下載Vue.js相關檔案,首頁在以下網址:「https://vuejs.org/v2/guide/installation.html」。

圖 1:下載Vue.js相關檔案。
在首頁選擇想要下載使用的版本,本文以Vue.js 2.6.10版為例,檔案分為兩種:
- 「vue.js」:除錯版(Development)的Vue.js函式庫,會包含一些空白字元、除錯資訊等等,在開發階段易於除錯。
- 「vue.min.js」:發行版(Production)的Vue.js函式庫,會移除一些不必要的空白字元、註解等等,讓檔案最小化,以求上線階段節省下載時間。
雖然不太可能發生,但若無除錯需求,在開發、上線階段都只需在網頁之中引用發行版(vue.min.js)即可,你可以將這個檔案放在網站應用程式專案之中。
接著便可以在HTML網頁之中引用下載下來的檔案,參考以下範例程式碼:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title> Document </title>
</head>
<body>
<h1> Demo </h1>
<script src="js/vue.min.js"> </script>
</body>
</html>
使用內容傳遞網路(CDN)
你也可以直接在網頁中,引用內容傳遞網路(Content delivery network或Content distribution network,縮寫:CDN)伺服器上的Vue.js程式庫,以下的連結可以下載到最新版本的Vue.js程式庫:
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
或者參考以下的連結,明確指定想要使用的Vue.js版本:
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
使用NPM下載
除了上述下在Vue.js檔案的方式之外,要安裝Vue.js還可以透過「npm」工具程式來進行下載。「npm」隨著Node.js散發,也就是說只要安裝Node.js就會自動安裝「npm」工具程式。Node.js:下載網址為:「https://nodejs.org/en/」。

圖 2:下載Node.js。
從官網下載適當版本後,進行安裝作業。Node.js安裝完成之後,可以在命令提示字元輸入以下「npm install」指令來安裝Vue.js套件:
npm install vue
這個命令執行結果請參考下圖所示:

圖 3:使用NPM下載並安裝Vue.js。
第一個Vue.js基本範例
我們來看第一個Vue.js基本範例,以了解Vue.js與DOM之間該如何互動,請參考以下範例程式碼:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title> Document </title>
</head>
<body>
<div id="divMsg">
<h1> {{ msg }} </h1>
</div>
<script src="js/vue.min.js"> </script>
<script >
var vm = new Vue({
el: '#divMsg',
data: {
msg: 'Hello World'
}
});
</script>
</body>
</html>
網頁中的「<div id="divMsg">」標籤使用宣告的方式,將資料更新到DOM,以便在網頁中印出「Hello World」訊息。訊息的顯示採用{{}}語法。接著在程式中,我們使用「new Vue({ })」建立Vue物件實體(Vue Instance),傳入一個Options物件當參數,利用「el」屬性指定DOM元素「#divMsg」,我們將此DOM元素視為容器(Container);「data」屬性設定為一個物件,其「msg」屬性的資料為「Hello World」,並透過{{ msg }}語法,將「Hello World」字串的值,更新到DOM物件「#divMsg」元素之中。這個範例執行結果請參考下圖:

圖 4:Vue.js基本範例執行結果。
Vue實體
每一個Vue應用程式都需要使用Vue函式建立一個Vue實體(Vue Instance),我們稱這個實體為「根Vue實體(root Vue instance)」。依照慣例,這個實體的變數名稱通常稱為「vm」,它是ViewModel的縮寫,當然你可以放心的自訂名稱。當你建立Vue物件實體(Vue Instance),可以傳入一個Options物件當參數,此物件可以定義資料(data)與方法(method),參考以下範例程式碼:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title> Document </title>
</head>
<body>
<div id="divMsg">
<h1> Employee Id : {{ empId }} </h1>
<h1> Employee Name : {{ empName }} </h1>
<h1> Employee Info : {{ showInfo() }} </h1>
</div>
<script src="js/vue.min.js"> </script>
<script>
var vm = new Vue({
el: '#divMsg',
data: {
empId: 1,
empName: 'Mary'
},
methods: {
showInfo: function () {
return this.empId + "," + this.empName;
}
}
});
console.log( vm.$data );
console.log( vm.$data.empName );
console.log( vm.empName );
</script>
</body>
</html>
Options參數物件包含一個名為「el」的屬性,被指派一個DOM元素的ID:「#divMsg」,「#」號代表ID選取器,而DIV標籤的ID為「divMsg」。接著在程式中定義一個「data」屬性,值是一個物件,包含「empId」、「empName」屬性。標籤中{{ empId }}將會被替代成「empId」的值「1」;而{{ empName }} 將會被替代成「empName」的值「Mary」。最後「data」物件,還包含一個「showInfo」函式,回傳「empId」、「empName」屬性值串接的字串;標籤中{{ showInfo() }}將會被替代成「showInfo」函式執行的回傳值。這個範例執行結果請參考下圖:

圖 5:範例執行結果。
範例結尾的三行JavaScript程式碼,利用console輸出除錯資訊到瀏覽器主控台。如果在Chrome瀏覽器執行上個範例的網頁,按下「F12」鍵開啟除錯工具(再按一次「F12」鍵可以關閉除錯工具),從除錯工具的主控台(Console)可以看到輸出以下內容:

圖 6:使用瀏覽器除錯主控台。
我們可以在程式碼中利用「vm.$data」取得Options物件的「data」屬性,此即為MVVM中的模型(Model)。而data物件的屬性會被轉換成getter/setter,例如「empId」屬性將被轉換成「get_empId(getter)」與「set_empId(setter)」函式。
雙向資料繫結
Vue.js專注在MVVM(Model - View - ViewModel)設計模式中的ViewModel層,透過雙向資料繫結語法,將檢視(View)與模型(Model)連結在一起。
- 模型(Model):Model是一個JavaScript物件,提供資料。
- 檢視(View):View是指由Vue實體負責管理的真正的DOM物件。
- 檢視模型(ViewModel):在Vue.js中,每一個Vue實體就是一個ViewModel,此物件同步View與Model。
使用Vue.js,不太需要直接操作DOM,當資料異動時,將會自動更新View。Vue.js使用宣告式(declarative)語法,透過「v-model」指示詞(directive),來達成雙向資料繫結,讓你很容易搜集使用者輸入資料,以及異動資料。參考以下範例程式碼:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title> Document </title>
</head>
<body>
<div id="divMsg">
<div> Employee Id :
<input type="text" v-model="empId">
</div>
<br />
<div> Employee Name :
<input type="text" v-model="empName">
</div>
<div> Employee Info : {{ showInfo() }} </div>
</div>
<script src="js/vue.min.js"></script>
<script>
var o = {
empId: 1,
empName: 'Mary'
};
var vm = new Vue({
el: '#divMsg',
data: o,
methods: {
showInfo: function () {
return this.empId + "," + this.empName;
}
}
});
</script>
</body>
</html>
這個範例程式的執行結果參考如下,當你在文字方塊中修改員工的資料時,異動的資料也會馬上顯示在下方區塊:

圖 7:範例執行結果。
使用元件(Component)
元件(Component)是可以被重複使用的Vue實體,因為元件是Vue實體,因此建立元件時,可以傳入Options參數物件,來設定data、methods等。
通常元件可以包含以下項目:
- HTML標籤:用來設定元件的結構。
- CSS樣式:用來設定元件的外觀,像字型、顏色、框線等等。
- JavaScript程式碼:設定元件的資料,以及元件的行為。
元件(Component)可以包含以下屬性:
- 「template」:指定元件要顯示的外觀,通常包含HTML標籤。
- 「props」:可以指定為字串陣列,或物件,用來從父元件傳送資料。
- 「data」:必需指定為一個回傳物件的函式,而不是一個純物件。如此可以讓元件的每一個實體都擁有自己的資料。
- 「events」:用來接聽事件。
- 「methods」:指定為函式,定義元件可以執行的行為。
- 「computed」:計算屬性,在相依項目變動時,能自動重新計算值,並更新到DOM。
在前文的範例中,我們已經看到了建立元件的第一種方式:
var vm = new Vue({
el: '#divMsg',
data: o,
methods: {
showInfo: function () {
return this.empId + "," + this.empName;
}
}
});
這種元件沒有對應的元件標籤,我們通常稱為主要容器元件(Main Container Component)。
使用Vue.component()函式建立元件
第二種建立元件的方式是採用「Vue.component()」函式,以此函式定義的元件可以允許你自訂元件標籤,並且能在網頁中重複的使用。以此函式建立的元件將會註冊在全域範圍(Global),直接可以在網頁程式之中使用。
以下是使用「Vue.component()」函式建立元件的範例程式:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title> Document </title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
<script id="my-template" type="x-template">
<div>
<label> {{promptText}} :</label>
<input type="text" v-model="myName" />
</div>
</script>
</head>
<body>
<div id="app">
<h2> {{title}} </h2>
<my-component v-bind:my-Name="userName"> </my-component>
</div>
<script>
Vue.component('my-component', {
template: '#my-template',
props: ['myName'],
data: function () {
return {
promptText: 'User Name'
}
}
});
var vm = new Vue({
el: '#app',
data: {
userName: 'Mary',
title: 'My App'
}
});
console.dir( vm.$data.userName );
</script>
</body>
</html>
我們利用<script id="my-template" type="x-template">區塊來定義元件的外觀,元件只能有一個根項目,因此範例中將元件的內容使用一個<div>標籤包起來:
<script id="my-template" type="x-template">
<div>
<label> {{promptText}} :</label>
<input type="text" v-model="myName" />
</div>
</script>
「Vue.component()」函式的第一個參數指定元件的名稱,元件的名稱可以採用兩種命名方式「kebab-case」或「PascalCase」。在此使用kebab-case命名法命名為「my-component」。元件接收一個「myName」props,用來傳送父元件資料(#app的userName)到子元件��my-component的myName)。
接著我們在程式中初始化根元件「#app」:
var vm = new Vue({
el: '#app',
data: {
userName: 'Mary',
title: 'My App'
}
});
在app中直接使用「my-component」標籤來插入元件:
<div id="app">
<h2> {{title}} </h2>
<my-component v-bind:my-Name="userName"> </my-component>
</div>
在HTML Attribute裏頭 「my-Name」大小寫視為相同,可以修改為:
<div id="app">
<h2> {{title}} </h2>
<my-component v-bind:my-name="userName"> </my-component>
</div>
這個範例程式的執行結果請參考下圖所示:

圖 8:使用Vue.component()函式建立元件範例。
我們也可以直接將樣板定義在「template」屬性之中,修改上例程式碼如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title> Document </title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"> </script>
</head>
<body>
<div id="app">
<h2> {{title}} </h2>
<my-component v-bind:my-Name="userName"> </my-component>
</div>
<script>
Vue.component('my-component', {
template: '<div class="myclass"><label>{{promptText}} :</label><input type="text" v-model="myName"></div>',
props: ['myName'],
data: function () {
return {
promptText: 'User Name'
}
}
});
var vm = new Vue({
el: '#app',
data: {
userName: 'Mary',
title :'My App'
}
});
console.dir( vm.$data.userName );
</script>
</body>
</html>
若要採用「PascalCase」命名元件名稱,請參考以下範例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title> Document </title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"> </script>
<script id="my-template" type="x-template">
<div>
<label> {{promptText}} :</label>
<input type="text" v-model="myName" />
</div>
</script>
</head>
<body>
<div id="app">
<h2> {{title}} </h2>
<my-Component v-bind:my-name="userName"> </my-Component>
</div>
<script>
Vue.component('MyComponent', {
template: '#my-template',
props: ['myName'],
data: function () {
return {
promptText: 'User Name'
}
}
});
var vm = new Vue({
el: '#app',
data: {
userName: 'Mary',
title: 'My App'
}
});
console.dir( vm.$data.userName );
</script>
</body>
</html>
建立區域元件(Local Component)
建立元件的第三種方式是使用區域元件(Local Component),它不是全域的,只能給特定的元件存取,因此很適合達到封裝(encapsulation)的效果。
參考以下範例程式碼,只要將一個有定義元件該有的屬性(template、props...等等)之物件指派給一個變數(myComponent),然後在「#app」元件中,便可以使用「components」屬性來使用「my-component」區域元件:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title> Document </title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"> </script>
<script id="my-template" type="x-template">
<div>
<label> {{promptText}} :</label>
<input type="text" v-model="myName" />
</div>
</script>
</head>
<body>
<div id="app">
<h2> {{title}} </h2>
<my-component v-bind:my-Name="userName"> </my-component>
</div>
<script>
var myComponent = {
template: '#my-template',
props: ['myName'],
data: function () {
return {
promptText: 'User Name'
}
}
};
var vm = new Vue({
el: '#app',
data: {
userName: 'Mary',
title :'My App'
},
components: {
'my-component': myComponent
}
});
console.dir( vm.$data.userName );
</script>
</body>
</html>
範例中Vue實體(#app)包含一個私有元件(Private Component):「my-component」,我們更改使用「kebab-case」命名法,以便在Vue實體中的HTML標籤內使用:
var vm = new Vue({
el: '#app',
data: {
userName: 'Mary',
title :'My App'
},
components: {
'my-component': myComponent
}
});
另外在我們在程式中定義了一個「myComponent」元件,「template」指定為「#my-template」:
var myComponent = {
template: '#my-template',
props: ['myName'],
data: function () {
return {
promptText: 'User Name'
}
}
};
「props」屬性是一個陣列,包含元件擁有的特性(attribute):「myName」。在元件中,「data」屬性必需是一個函式,用來回傳資料。在範例中,回傳一個物件,包含「promptText」屬性,以在元件樣板中{{promptText}}所在位置顯示提示字串「User Name」。
比較特別的是,範例中元件「props」擁有的「myName」使用camel Cased命名法,而在DOM樣板中,大小寫視為相同,因此在宣告式的標籤中,建議使用kebab-case命名法「my-Name」:
<my-component v-bind:my-Name="userName"> </my-component>
此範例的執行結果如圖 8所示。