Vue快速上手
Vue是一個前端框架,簡單來說,其目標是通過儘可能簡單的 API 實現響應的資料繫結和組合的檢視元件。
國際慣例HelloWorld
<!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/[email protected]/dist/vue.js"></script> </head> <body> <div id="app"> {{ msg }} </div> <script> var app=new Vue({ el:'#app', data:{ msg:'Hello World!' } }); </script> </body> </html>
[1]Vue例項
建立一個Vue例項
Var vm = new Vue({ //選項 })
當建立一個Vue例項時,你可以傳入一個選項物件,該物件可以建立你想要的行為。
一個Vue應用由一個通過 new Vue 建立的 根Vue例項 ,以及可選的巢狀的,可複用的元件樹組成。所有的Vue元件都是Vue例項,並且接受相同的選項物件(一些根例項特有的選項除外)。
資料響應
當一個 Vue 例項被建立時,它向 Vue 的響應式系統中加入了其 data 物件中能找到的所有的屬性。當這些屬性的值發生改變時,檢視將會產生“響應”,即 匹配更新為新的值 。
// 我們的資料物件 var data = { a: 1 } // 該物件被加入到一個 Vue 例項中 var vm = new Vue({ data: data }) // 獲得這個例項上的屬性 // 返回源資料中對應的欄位 vm.a == data.a // => true // 設定屬性也會影響到原始資料 vm.a = 2 data.a // => 2 // ……反之亦然 data.a = 3 vm.a // => 3
值得注意的是只有當例項建立時 data 中存在的屬性才是 響應式 的。
例項生命週期鉤子
每個 Vue 例項在被建立時都要經過一系列的初始化過程——例如,需要設定資料監聽、編譯模板、將例項掛載到 DOM 並在資料變化時更新 DOM 等。同時在這個過程中也會執行一些叫做 生命週期鉤子 的函式,這給了使用者在不同階段執行自己的程式碼的機會。
比如 created
鉤子可以用來在一個例項被建立之後執行程式碼:
new Vue({ data: { a: 1 }, created: function () { // `this` 指向 vm 例項 console.log('a is: ' + this.a) } }) // => "a is: 1"
也有一些其它的鉤子,在例項生命週期的不同階段被呼叫,如 mounted
、 updated
和 destroyed
。生命週期鉤子的 this
上下文指向呼叫它的 Vue 例項。

Vue例項的生命週期
[2]模板語法
插值
- 文字
<span>Message: {{ msg }}</span>
Mustache 標籤將會被替代為對應資料物件上 msg 屬性的值。無論何時,繫結的資料物件上 msg 屬性發生了改變,插值處的內容都會更新。
- 原始HTML
雙大括號會將資料解釋為 普通文字 ,而非 HTML 程式碼。為了輸出真正的 HTML,你需要使用 v-html 指令 - HTML屬性
Mustache 語法不能作用在 HTML 屬性上,遇到這種情況應該使用 v-bind 指令:
<div v-bind:id="dynamicId"></div>
-
使用JavaScript表示式
迄今為止,在我們的模板中,我們一直都只繫結簡單的屬性鍵值。但實際上,對於所有的資料繫結,Vue.js 都提供了完全的 JavaScript 表示式支援。
{{ number + 1 }} {{ ok ? 'YES' : 'NO' }} {{ message.split('').reverse().join('') }} <div v-bind:id="'list-' + id"></div>
這些表示式會在所屬 Vue 例項的資料作用域下作為 JavaScript 被解析。有個限制就是,每個繫結都只能包含 單個表示式 。
指令
指令 (Directives) 是帶有 v- 字首的特殊特性。指令特性的值預期是單個 JavaScript 表示式 (v-for 是例外情況,稍後我們再討論)。指令的職責是,當表示式的值改變時,將其產生的連帶影響,響應式地作用於 DOM。比如:
<p v-if="seen">現在你看到我了</p>
這裡,v-if 指令將根據表示式 seen 的值的真假來插入/移除 <p> 元素。
-
引數
一些指令能夠接收一個“引數”,在指令名稱之後以 冒號 表示。例如,v-bind 指令可以用於響應式地更新 HTML 特性:
<a v-bind:href="url">...</a>
在這裡 href 是引數,告知 v-bind 指令將該元素的 href 特性與表示式 url 的值繫結。
另一個例子是 v-on 指令,它用於監聽 DOM 事件:
<a v-on:click="doSomething">...</a>
在這裡引數是監聽的事件名。我們也會更詳細地討論事件處理。
-
修飾符
修飾符 (Modifiers) 是以半形句號 . 指明的特殊字尾,用於指出一個指令應該以特殊方式繫結。例如,.prevent 修飾符告訴 v-on 指令對於觸發的事件呼叫 event.preventDefault():
<form v-on:submit.prevent="onSubmit">...</form>
縮寫
Vue.js 為 v-bind 和 v-on 這兩個最常用的指令,提供了特定簡寫:
<!-- 完整語法 --> <a v-bind:href="url">...</a> <!-- 縮寫 --> <a :href="url">...</a> <!-- 完整語法 --> <a v-on:click="doSomething">...</a> <!-- 縮寫 --> <a @click="doSomething">...</a>
[3]計算屬性和偵聽器
計算屬性(computed properties)
模板內的表示式非常便利,但是設計它們的初衷是用於簡單運算的。在模板中放入太多的邏輯會讓模板過重且難以維護。對於任何複雜邏輯,都應該使用 計算屬性 。
<div id="example"> <p>Original message: "{{ message }}"</p> <p>Computed reversed message: "{{ reversedMessage }}"</p> </div> var vm = new Vue({ el: '#example', data: { message: 'Hello' }, computed: { // 計算屬性的 getter reversedMessage: function () { // `this` 指向 vm 例項 return this.message.split('').reverse().join('') } } })
這裡我們聲明瞭一個計算屬性 reversedMessage。我們提供的函式將用作屬性 vm.reversedMessage 的 getter 函式.
你可以像繫結普通屬性一樣在模板中繫結計算屬性。Vue 知道 vm.reversedMessage 依賴於 vm.message,因此當 vm.message 發生改變時,所有依賴 vm.reversedMessage 的繫結也會更新。
方法
我們也可以在表示式中呼叫方法來達到同樣的效果:
<p>Reversed message: "{{ reversedMessage() }}"</p> methods: { reversedMessage: function () { return this.message.split('').reverse().join('') } }
然而,不同的是 計算屬性是基於它們的依賴進行快取的 。只在相關依賴發生改變時它們才會重新求值。這就意味著只要 message 還沒有發生改變,多次訪問 reversedMessage 計算屬性會立即返回之前的計算結果,而不必再次執行函式。
偵聽屬性
Vue 提供了一種更通用的方式來觀察和響應 Vue 例項上的資料變動: 偵聽屬性
<div id="app"> {{ msg }} </div> <script> var app=new Vue({ el:'#app', data:{ msg:'Hello World!', }, watch:{ msg:function(val){ console.log("val now is changing to:"+val); } } }); </script>
然而,當你有一些資料需要隨著其它資料變動而變動時,通常更好的做法是使用計算屬性。
Class與Style的資料繫結
操作元素的 class 列表和內聯樣式是資料繫結的一個常見需求。因為它們都是屬性,所以我們可以用 v-bind 處理它們:只需要通過表示式計算出字串結果即可。不過,字串拼接麻煩且易錯。因此,在將 v-bind 用於 class 和 style 時,Vue.js 做了專門的增強。表示式結果的型別除了字串之外,還可以是物件或陣列。此處不進行贅述。
[4]條件渲染
<h1 v-if="ok">Yes</h1> //此處的ok是一個屬性 <h1 v-else>No</h1>
在<template>元素上使用v-if條件渲染分組
<template v-if="ok"> <h1>Title</h1> <p>Paragraph 1</p> <p>Paragraph 2</p> </template>
v-else-if
<div v-if="type === 'A'"> A </div> <div v-else-if="type === 'B'"> B </div> <div v-else-if="type === 'C'"> C </div> <div v-else> Not A/B/C </div>
v-show
<h1 v-show="ok">Hello!</h1>
不同的是帶有 v-show 的元素 始終會被渲染 並保留在 DOM 中。v-show 只是簡單地切換元素的 CSS 屬性 display
[5]列表渲染
我們用 v-for 指令根據一組陣列的選項列表進行渲染。v-for 指令需要使用 item in items 形式的特殊語法,items 是源資料陣列並且 item 是陣列元素迭代的別名。
<ul id="example-1"> <li v-for="item in items"> {{ item.message }} </li> </ul> <ul id="example-2"> <li v-for="(item, index) of items">//支援一個可選的第二引數作為索引,of和in可以互換 {{ parentMessage }} - {{ index }} - {{ item.message }} </li> </ul> var example1 = new Vue({ el: '#example-1', data: { items: [ { message: 'Foo' }, { message: 'Bar' } ] } })
v-for還可以迭代一個物件的屬性:
<ul id="v-for-object" class="demo"> <li v-for="value in object"> {{ value }} </li> </ul> <div v-for="(value, key, index) in object">//同樣具有多個可選引數 {{ index }}. {{ key }}: {{ value }} </div> new Vue({ el: '#v-for-object', data: { object: { firstName: 'John', lastName: 'Doe', age: 30 } } })
呼叫一些陣列的方法將會觸發檢視更新,值得注意的是,利用索引直接設定一個項或者修改陣列長度的時候不能被Vue檢測觸發更新。
除此以外,對於物件更改的檢測,以及顯示過濾結果,此處不贅述
[6]事件處理
可以用 v-on 指令監聽 DOM 事件,並在觸發時執行一些 JavaScript 程式碼。
<div id="example-1"> <button v-on:click="counter += 1">Add 1</button> <p>The button above has been clicked {{ counter }} times.</p> </div>
對於更加複雜的事件邏輯,v-on可以接收一個需要呼叫的方法名稱:
<div id="app"> <button v-on:click="greet">Add</button> </div> <script> var app=new Vue({ el:'#app', methods:{ greet:function(event){ alert(event); } }, }); </script>
Vue.js為v-on提供了 事件修飾符 :
<!-- 阻止單擊事件繼續傳播 --> <a v-on:click.stop="doThis"></a> <!-- 提交事件不再過載頁面 --> <form v-on:submit.prevent="onSubmit"></form> <!-- 修飾符可以串聯 --> <a v-on:click.stop.prevent="doThat"></a> <!-- 只有修飾符 --> <form v-on:submit.prevent></form> <!-- 新增事件監聽器時使用事件捕獲模式 --> <!-- 即元素自身觸發的事件先在此處理,然後才交由內部元素進行處理 --> <div v-on:click.capture="doThis">...</div> <!-- 只當在 event.target 是當前元素自身時觸發處理函式 --> <!-- 即事件不是從內部元素觸發的 --> <div v-on:click.self="doThat">...</div>
[7]表單輸入繫結
你可以用 v-model 指令在表單 <input>、<textarea> 及 <select> 元素上建立 雙向資料繫結 。它會根據控制元件型別自動選取正確的方法來更新元素
<input v-model="message" placeholder="edit me"> <p>Message is: {{ message }}</p>
此處對於不同的輸入控制元件均有類似的用法,此處不贅述
[8]元件基礎
new Vue({ el: '#components-demo' }) // 定義一個名為 button-counter 的新元件 Vue.component('button-counter', { data: function () { return { count: 0 } }, template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>' })
元件是可複用的 Vue 例項,且帶有一個 名字 :在這個例子中是 <button-counter>。我們可以在一個通過 new Vue 建立的 Vue 根例項中,把這個元件作為自定義元素來使用。
因為元件是可複用的 Vue 例項,所以它們與 new Vue 接收相同的選項,例如 data、computed、watch、methods 以及生命週期鉤子等。僅有的例外是像 el 這樣根例項特有的選項。
data必須是一個函式
之前我們所建立的Vue根例項,data直接提供一個物件即可。
但一個元件的 data 選項必須是一個函式,因此每個例項可以維護一份被返回物件的 獨立的拷貝 :
data: function () { return { count: 0 } }
元件組織
為了能在模板中使用,這些元件必須先註冊以便 Vue 能夠識別。這裡有兩種元件的註冊型別:全域性註冊和區域性註冊。至此,我們的元件都只是通過 Vue.component 全域性註冊的:
Vue.component('my-component-name', { // ... options ... })
全域性註冊的元件可以用在其被註冊之後的任何 (通過 new Vue) 新建立的 Vue 根例項,也包括其元件樹中的所有子元件的模板中。
通過Prop向子元件傳遞資料
Prop實際上是你可以在元件上註冊的一些自定義屬性(屬性就是class之類)。
Vue.component('blog-post', { props: ['title'], template: '<h3>{{ title }}</h3>' })
一個元件預設可以擁有任意數量的 prop,任何值都可以傳遞給任何 prop。在上述模板中,你會發現我們能夠在元件例項中訪問這個值,就像訪問 data 中的值一樣。
一個 prop 被註冊之後,你就可以像這樣把資料作為一個自定義屬性傳遞進來:
<blog-post title="My journey with Vue"></blog-post> <blog-post title="Blogging with Vue"></blog-post> <blog-post title="Why Vue is so fun"></blog-post>