上篇講到vue的使用方法,今天這一篇介紹vue的實操,可以大家更加加強去學習web前端vue技術。
第一節 Music項目環境第一部分
本屆作業
- 聊一聊React和Vue的差別
- 老版本的項目環境如何建立項目
第二節 Vue API 第二部分
模闆文法
文本
資料綁定最常見的形式就是使用“Mustache”文法 (雙大括号) 的文本插值:
<
Mustache 标簽将會被替代為對應資料對象上 msg 屬性的值。無論何時,綁定的資料對象上 msg屬性發生了改變,插值處的内容都會更新。
通過使用 v-once 指令,你也能執行一次性地插值,當資料改變時,插值處的内容不會更新。但請留心這會影響到該節點上的其它資料綁定:
<
原始HTML
雙大括号會将資料解釋為普通文本,而非 HTML 代碼。為了輸出真正的 HTML,你需要使用 v-html 指令:
<
這個 span 的内容将會被替換成為屬性值 rawHtml,直接作為 HTML——會忽略解析屬性值中的資料綁定。注意,你不能使用 v-html 來複合局部模闆,因為 Vue 不是基于字元串的模闆引擎。反之,對于使用者界面 (UI),元件更适合作為可重用和可組合的基本機關。
提示:
你的站點上動态渲染的任意 HTML 可能會非常危險,因為它很容易導緻 XSS 攻擊。請隻對可信内容使用 HTML 插值,絕不要對使用者提供的内容使用插值。
特性
Mustache 文法不能作用在 HTML 特性上,遇到這種情況應該使用 v-bind 指令:
<
使用JavaScript表達式
迄今為止,在我們的模闆中,我們一直都隻綁定簡單的屬性鍵值。但實際上,對于所有的資料綁定,Vue.js 都提供了完全的 JavaScript 表達式支援。
<
這些表達式會在所屬 Vue 執行個體的資料作用域下作為 JavaScript 被解析。有個限制就是,每個綁定都隻能包含
單個表達式,是以下面的例子都
不會生效。
<!-- 這是語句,不是表達式 -->
{{ var a = 1 }}
<!-- 流控制也不會生效,請使用三元表達式 -->
{{ if (ok) { return message } }}
縮寫
v- 字首作為一種視覺提示,用來識别模闆中 Vue 特定的特性。當你在使用 Vue.js 為現有标簽添加動态行為 (dynamic behavior) 時,v- 字首很有幫助,然而,對于一些頻繁用到的指令來說,就會感到使用繁瑣。同時,在建構由 Vue 管理所有模闆的單頁面應用程式 (SPA - single page application)時,v- 字首也變得沒那麼重要了。是以,Vue 為 v-bind 和 v-on 這兩個最常用的指令,提供了特定簡寫:
v-bind 縮寫
<!-- 完整文法 -->
<a v-bind:href="url" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" >...</a>
<!-- 縮寫 -->
<a :href="url" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" >...</a>
v-on縮寫
<!-- 完整文法 -->
<a v-on:click="doSomething">...</a>
<!-- 縮寫 -->
<a @click="doSomething">...</a>
它們看起來可能與普通的 HTML 略有不同,但 : 與 @ 對于特性名來說都是合法字元,在所有支援 Vue 的浏覽器都能被正确地解析。而且,它們不會出現在最終渲染的标記中。縮寫文法是完全可選的,但随着你更深入地了解它們的作用,你會慶幸擁有它們
條件渲染
v-if
v-if 指令用于條件性地渲染一塊内容。這塊内容隻會在指令的表達式傳回 truthy 值的時候被渲染。
<h1 v-if="awesome">Vue is awesome!</h1>
也可以用 v-else 添加一個“else 塊”:
<h1 v-if="awesome">Vue is awesome!</h1>
<h1 v-else>Oh no </h1>
在 <template> 元素上使用 v-if 條件渲染分組
因為 v-if 是一個指令,是以必須将它添加到一個元素上。但是如果想切換多個元素呢?此時可以把一個 <template> 元素當做不可見的包裹元素,并在上面使用 v-if。最終的渲染結果将不包含 <template> 元素。
<
v-else
你可以使用 v-else 指令來表示 v-if 的“else 塊”
<
v-else 元素必須緊跟在帶 v-if 或者 v-else-if 的元素的後面,否則它将不會被識别。
v-else-if
v-else-if,顧名思義,充當 v-if 的“else-if 塊”,可以連續使用:
<
A
</
B
</
C
</
v-show
另一個用于根據條件展示元素的選項是 v-show 指令。用法大緻一樣:
<
不同的是帶有 v-show 的元素始終會被渲染并保留在 DOM 中。v-show 隻是簡單地切換元素的 CSS 屬性 display。
v-if vs v-show
v-if 是“真正”的條件渲染,因為它會確定在切換過程中條件塊内的事件監聽器和子元件适當地被銷毀和重建。
v-if 也是
惰性的:如果在初始渲染時條件為假,則什麼也不做——直到條件第一次變為真時,才會開始渲染條件塊。
相比之下,v-show 就簡單得多——不管初始條件是什麼,元素總是會被渲染,并且隻是簡單地基于 CSS 進行切換。
一般來說,v-if 有更高的切換開銷,而 v-show 有更高的初始渲染開銷。是以,如果需要非常頻繁地切換,則使用 v-show 較好;如果在運作時條件很少改變,則使用 v-if 較好。
清單渲染
用 v-for 把一個數組對應為一組元素
我們可以用 v-for 指令基于一個數組來渲染一個清單。v-for 指令需要使用 item in items 形式的特殊文法,其中 items 是源資料數組,而 item 則是被疊代的數組元素的
别名。
<
在 v-for 裡使用對象
你也可以用 v-for 來周遊一個對象的屬性。
<
數組更新檢測
變異方法
Vue 将被偵聽的數組的變異方法進行了包裹,是以它們也将會觸發視圖更新。這些被包裹過的方法包括:
- push()
- pop()
- shift()
- unshift()
- splice()
- sort()
- reverse()
替換數組
變異方法,顧名思義,會改變調用了這些方法的原始數組。相比之下,也有非變異 (non-mutating method) 方法,例如 filter()、concat() 和 slice() 。它們不會改變原始數組,而總是傳回一個新數組。當使用非變異方法時,可以用新數組替換舊數組:
example1.items = example1.items.filter(function (item) {
return item.message.match(/Foo/)
})
你可能認為這将導緻 Vue 丢棄現有 DOM 并重新渲染整個清單。幸運的是,事實并非如此。Vue 為了使得 DOM 元素得到最大範圍的重用而實作了一些智能的啟發式方法,是以用一個含有相同元素的數組去替換原來的數組是非常高效的操作。
對象變更檢測注意事項
還是由于 JavaScript 的限制,Vue 不能檢測對象屬性的添加或删除:
你還可以使用 vm.$set 執行個體方法,它隻是全局 Vue.set 的别名:
vm.$set(vm.userProfile, 'age', 27)
本屆作業
- 模闆文法中可以存在的語句有那些
- 說出v-if和v-show的差別
- 編寫代碼,實作給定數組的清單渲染内容:[10,20,30,40]
第三節 Vue API第一部分
事件處理
監聽事件
可以用 v-on 指令監聽 DOM 事件,并在觸發時運作一些 JavaScript 代碼。
<
事件處理方法
然而許多事件處理邏輯會更為複雜,是以直接把 JavaScript 代碼寫在 v-on 指令中是不可行的。是以 v-on 還可以接收一個需要調用的方法名稱
<
// 也可以用 JavaScript 直接調用方法
example2.greet() // => 'Hello Vue.js!'
内聯處理器中的方法
除了直接綁定到一個方法,也可以在内聯 JavaScript 語句中調用方法
<
new Vue({
el: '#example-3',
methods: {
say: function (message) {
alert(message)
}
}
})
有時也需要在内聯語句處理器中通路原始的 DOM 事件。可以用特殊變量 $event 把它傳入方法:
<
// ...
methods: {
warn: function (message, event) {
// 現在我們可以通路原生事件對象
if (event) event.preventDefault()
alert(message)
}
}
事件修飾符
在事件處理程式中調用 event.preventDefault() 或 event.stopPropagation() 是非常常見的需求。盡管我們可以在方法中輕松實作這點,但更好的方式是:方法隻有純粹的資料邏輯,而不是去處理 DOM 事件細節。
為了解決這個問題,Vue.js 為 v-on 提供了事件修飾符。之前提過,修飾符是由點開頭的指令字尾來表示的。
- .stop
- .prevent
- .capture
- .self
- .once
- .passive
<!-- 阻止單擊事件繼續傳播 -->
計算屬性和偵聽器
計算屬性
模闆内的表達式非常便利,但是設計它們的初衷是用于簡單運算的。在模闆中放入太多的邏輯會讓模闆過重且難以維護。例如:
<
在這個地方,模闆不再是簡單的聲明式邏輯。你必須看一段時間才能意識到,這裡是想要顯示變量 message 的翻轉字元串。當你想要在模闆中多次引用此處的翻轉字元串時,就會更加難以處理。
是以,對于任何複雜邏輯,你都應當使用計算屬性。
<
var vm = new Vue({
el: '#example',
data: {
message: 'Hello'
},
computed: {
// 計算屬性的 getter
reversedMessage: function () {
// `this` 指向 vm 執行個體
return this.message.split('').reverse().join('')
}
}
})
你可以像綁定普通屬性一樣在模闆中綁定計算屬性。Vue 知道 vm.reversedMessage 依賴于 vm.message,是以當 vm.message 發生改變時,所有依賴 vm.reversedMessage 的綁定也會更新。而且最妙的是我們已經以聲明的方式建立了這種依賴關系:計算屬性的 getter 函數是沒有副作用 (side effect) 的,這使它更易于測試和了解。
計算屬性緩存 vs 方法
你可能已經注意到我們可以通過在表達式中調用方法來達到同樣的效果:
<
// 在元件中
methods: {
reversedMessage: function () {
return this.message.split('').reverse().join('')
}
}
我們可以将同一函數定義為一個方法而不是一個計算屬性。兩種方式的最終結果确實是完全相同的。然而,不同的是計算屬性是基于它們的響應式依賴進行緩存的。隻在相關響應式依賴發生改變時它們才會重新求值。這就意味着隻要 message 還沒有發生改變,多次通路 reversedMessage 計算屬性會立即傳回之前的計算結果,而不必再次執行函數。
偵聽器
雖然計算屬性在大多數情況下更合适,但有時也需要一個自定義的偵聽器。這就是為什麼 Vue 通過 watch 選項提供了一個更通用的方法,來響應資料的變化。當需要在資料變化時執行異步或開銷較大的操作時,這個方式是最有用的。
<
<!-- 因為 AJAX 庫和通用工具的生态已經相當豐富,Vue 核心代碼沒有重複 -->
在這個示例中,使用 watch 選項允許我們執行異步操作 (通路一個 API),限制我們執行該操作的頻率,并在我們得到最終結果前,設定中間狀态。這些都是計算屬性無法做到的。
Class與Style綁定
操作元素的 class 清單和内聯樣式是資料綁定的一個常見需求。因為它們都是屬性,是以我們可以用 v-bind 處理它們:隻需要通過表達式計算出字元串結果即可。不過,字元串拼接麻煩且易錯。是以,在将 v-bind 用于 class 和 style 時,Vue.js 做了專門的增強。表達式結果的類型除了字元串之外,還可以是對象或數組。
綁定 HTML Class
對象文法
我們可以傳給 v-bind:class 一個對象,以動态地切換 class:
<
上面的文法表示 active 這個 class 存在與否将取決于資料屬性 isActive 的 truthiness。
你可以在對象中傳入更多屬性來動态切換多個 class。此外,v-bind:class 指令也可以與普通的 class 屬性共存。當有如下模闆:
<
和如下 data:
data: {
isActive: true,
hasError: false
}
結果渲染為:
<
當 isActive 或者 hasError 變化時,class 清單将相應地更新。例如,如果 hasError 的值為 true,class 清單将變為 "static active text-danger"。
數組文法
我們可以把一個數組傳給 v-bind:class,以應用一個 class 清單:
<
data: {
activeClass: 'active',
errorClass: 'text-danger'
}
綁定内聯樣式
對象文法
v-bind:style 的對象文法十分直覺——看着非常像 CSS,但其實是一個 JavaScript 對象。CSS 屬性名可以用駝峰式 (camelCase) 或短橫線分隔 (kebab-case,記得用引号括起來) 來命名:
<
data: {
activeColor: 'red',
fontSize: 30
}
直接綁定到一個樣式對象通常更好,這會讓模闆更清晰:
<
data: {
styleObject: {
color: 'red',
fontSize: '13px'
}
}
數組文法
v-bind:style 的數組文法可以将多個樣式對象應用到同一個元素上:
<
提示:
當 v-bind:style 使用需要添加浏覽器引擎字首的 CSS 屬性時,如 transform,Vue.js 會自動偵測并添加相應的字首。
表單輸入與綁定
你可以用 v-model 指令在表單 <input>、<textarea> 及 <select> 元素上建立雙向資料綁定。它會根據控件類型自動選取正确的方法來更新元素。盡管有些神奇,但 v-model 本質上不過是文法糖。它負責監聽使用者的輸入事件以更新資料,并對一些極端場景進行一些特殊處理。
提示:
v-model 會忽略所有表單元素的 value、checked、selected 特性的初始值而總是将 Vue 執行個體的資料作為資料來源。你應該通過 JavaScript 在元件的 data 選項中聲明初始值。
v-model 在内部為不同的輸入元素使用不同的屬性并抛出不同的事件:
- text 和 textarea 元素使用 value 屬性和 input 事件;
- checkbox 和 radio 使用 checked 屬性和 change 事件;
- select 字段将 value 作為 prop 并将 change 作為事件。
文本
<
修飾符
.lazy
在預設情況下,v-model 在每次 input 事件觸發後将輸入框的值與資料進行同步 (除了上述輸入法組合文字時)。你可以添加 lazy 修飾符,進而轉變為使用 change 事件進行同步
<!-- 在“change”時而非“input”時更新 -->
.number
如果想自動将使用者的輸入值轉為數值類型,可以給 v-model 添加 number 修飾符:
<
這通常很有用,因為即使在 type="number" 時,HTML 輸入元素的值也總會傳回字元串。如果這個值無法被 parseFloat() 解析,則會傳回原始的值。
.trim
如果要自動過濾使用者輸入的首尾空白字元,可以給 v-model 添加 trim 修飾符:
<
本節作業
- 實作清單資料的點選事件
- 實作點選事件阻止冒泡
- 實作文本的雙向資料綁定
第四節 Vue 元件
單檔案元件
檔案擴充名為 .vue 的 single-file components(單檔案元件) 為以上所有問題提供了解決方法,并且還可以使用 webpack 或 Browserify 等建構工具。
這是一個檔案名為 Hello.vue 的簡單執行個體:
元件複用
你可以将元件進行任意次數的複用:
<
注意當點選按鈕時,每個元件都會各自獨立維護它的 count。因為你每用一次元件,就會有一個它的新執行個體被建立。
data 必須是一個函數
當我們定義這個 <button-counter> 元件時,你可能會發現它的 data 并不是像這樣直接提供一個對象:
data: {
count: 0
}
取而代之的是,一個元件的 data 選項必須是一個函數,是以每個執行個體可以維護一份被傳回對象的獨立的拷貝:
data: function () {
return {
count: 0
}
}
如果 Vue 沒有這條規則,點選一個按鈕就可能會像如下代碼一樣影響到其它所有執行個體:
Props
早些時候,我們提到了建立一個博文元件的事情。問題是如果你不能向這個元件傳遞某一篇博文的标題或内容之類的我們想展示的資料的話,它是沒有辦法使用的。這也正是 prop 的由來。
Prop 是你可以在元件上注冊的一些自定義特性。當一個值傳遞給一個 prop 特性的時候,它就變成了那個元件執行個體的一個屬性。為了給博文元件傳遞一個标題,我們可以用一個 props 選項将其包含在該元件可接受的 prop 清單中:
<
一個元件預設可以擁有任意數量的 prop,任何值都可以傳遞給任何 prop。在上述模闆中,你會發現我們能夠在元件執行個體中通路這個值,就像通路 data 中的值一樣。
一個 prop 被注冊之後,你就可以像這樣把資料作為一個自定義特性傳遞進來:
<
然而在一個典型的應用中,你可能在 data 裡有一個博文的數組:
new Vue({
el: '#blog-post-demo',
data: {
posts: [
{ id: 1, title: 'My journey with Vue' },
{ id: 2, title: 'Blogging with Vue' },
{ id: 3, title: 'Why Vue is so fun' }
]
}
})
并想要為每篇博文渲染一個元件:
<
如上所示,你會發現我們可以使用 v-bind 來動态傳遞 prop。這在你一開始不清楚要渲染的具體内容,比如從一個 API 擷取博文清單的時候,是非常有用的。
本節作業
- 單檔案元件的重要性
- 解釋為什麼Data必須是一個函數
- Props如何傳遞資料