1. 程式人生 > >Vue.js 2.0 教程精華梳理(一) 基礎

Vue.js 2.0 教程精華梳理(一) 基礎

Vue.js

第一部分 Vue.js 介紹

Vue.js(讀音 /vjuː/, 類似於 view) 是一套構建使用者介面的 漸進式框架。與其他重量級框架不同的是,Vue 採用自底向上增量開發的設計。Vue 的核心庫只關注檢視層,並且非常容易學習,非常容易與其它庫或已有專案整合。另一方面,Vue 完全有能力驅動採用單檔案元件和Vue生態系統支援的庫開發的複雜單頁應用。Vue沒有完全遵循MVVM格式,但Vue的設計無疑受到了它的啟發。

1.1 瀏覽器限制

Vue.js 不支援 IE8 及其以下版本,因為 Vue.js 使用了 IE8 不能模擬的 ECMAScript 5 特性(Object.defineProperty)。 Vue.js 支援所有相容 ECMAScript 5 的瀏覽器。

1.2 開發版本與生產版本

  1. 開發版本——包含完整的警告和除錯模式
  2. 生產版本——刪除了警告,23.55kb min+gzip

1.3 引入vue.js

當前vue.js版本2.0

<script src="https://unpkg.com/vue/dist/vue.js">
第二部分 Vue.js基礎

2.1 hello world

  1. <div id="app">
  2. {{ message }}
  3. </div>
  4. var app = new Vue({
  5. el: '#app',
  6. data: {
  7. message: 'Hello Vue!'
  8. }
  9. })

瀏覽器渲染結果:

Hello Vue!

Vue使資料和 DOM 被繫結在一起,所有的元素都是響應式的。當app.message改變時,會引起DOM的重新渲染。

2.2 Vue例項

2.2.1 選項物件

  1. <div id='app'></div>
  2. var vm = new Vue({
  3. // 選項物件
  4. })

在例項化 Vue 時,需要傳入一個選項物件,它可以包含資料、模板、掛載元素、方法、生命週期鉤子等選項。

選項物件包含常用的屬性包括,在下文還會進行拓展:

  1. var vm = {
  2. el:'', // 以CSS選擇器的形式選擇根元素
  3. data:{
  4. message
    :'Hello Vue!'
  5. }, // 資料物件
  6. methods:{
  7. sayHello:function () {
  8. alert(this.message)
  9. }
  10. }, //方法物件,注意可數複數後面加s
  11. ... ...
  12. }

2.2.2 代理data

Vue例項,即vm會代理選項物件中data物件裡的所有屬性,已上面建立的例項為例:

vm.message // =>Hello Vue!

在選項物件裡,this表示構造器的例項,所以在methods物件中的方法也使用this.屬性獲取data裡的屬性:

  1. ……
  2. methods:{
  3. sayHello:function () {
  4. alert(this.message) // =>Hello Vue!
  5. }
  6. },
  7. ……

更常見的是data是一個外部的變數

  1. var userInfo = {name:'Kyle Hu',age:20}
  2. ……
  3. data: userInfo
  4. ……

此時data和userInfo是雙向繫結的,二者有一方改變,對方都會改變。注意,userInfo一直存在在記憶體中。

就像你在寫node程式時不能使用exports = function () {}匯出模組一樣,你不能像下面這樣試圖改變選項物件所繫結的data變數,因為這樣完全破壞了data與vm的引用關係

  1. <div>{{age}}</div>
  2. var userInfo = {name:'Kyle Hu',age:20}
  3. ……
  4. data: userInfo
  5. ……
  6. userInfo.age = 15; // DOM渲染成15
  7. vm.age = 16; // DOM渲染成16
  8. userInfo = {name:'Kyle Hu',age:22}; // 引用關係被破壞,DOM不會重新渲染
  9. userInfo.age = 25; // 引用關係被破壞,DOM不會重新渲染
  10. vm.age = 23; // DOM被渲染成23

2.2.3 例項屬性與方法

既然vm.屬性代理的是vm選項物件中的data物件中的屬性,那麼,我們想要訪問諸如el,data等直接定義在選項物件裡的屬性怎麼辦呢?

Vue暴露了一些例項屬性。如要訪問諸如el,data這樣的選項物件屬性,則需在前面加上$,例如:

  1. vm.$el // =>HTMLXXXDOM
  2. vm.$data // => {message:'Hello Vue!'}

Vue還暴露了一些例項方法(不是methods裡的方法),與例項屬性相同,前面也加上$。比如監控元素改變的$watch方法

  1. vm.$watch('a', function (newVal, oldVal) {
  2. // 這個回撥將在 `vm.a` 改變後呼叫
  3. })

2.2.4 例項的宣告週期

2.3 模板語法

Vue.js 使用了基於 HTML 的模版語法,允許開發者宣告式地將 DOM 繫結至底層 Vue 例項的資料。所有 Vue.js 的模板都是合法的 HTML ,所以能被遵循規範的瀏覽器和 HTML 解析器解析。 在底層的實現上, Vue 將模板編譯成虛擬 DOM 渲染函式。結合響應系統,在應用狀態改變時, Vue 能夠智慧地計算出重新渲染元件的最小代價並應用到 DOM 操作上。 如果你熟悉虛擬 DOM 並且偏愛 JavaScript 的原始力量,你也可以不用模板,直接寫渲染(render)函式,使用可選的 JSX 語法。

2.3.1 插值

(1) 文字,使用 “Mustache” 語法(雙大括號語法)

<div>{{message}}</div>

(2)不隨vm.data變化的文字

<div v-once>{{message}}</div>

(3)純HTML,注意防止XSS攻擊

<div v-html="HTMLElement"></div>

(4)屬性

<button v-bind:id="btn_id"  v-bind:disabled="check">click me</button>

如果check的值是false,則disabled屬性將不會被渲染。以v-開頭的是Vue.js的指令,你馬上就能看到如何使用它們。

*>>注意:Vue.js1.x版本中的`{{{}}}、{{}}`等語法已被Vue.js 2.x淘汰**

2.3.2 表示式

可以在指令及{{}}中使用表示式,事實上,常量或變數的名稱就是最簡單的表示式。Vue可以通過是否帶引號來判斷一個表示式是一個變數還是一個常量字串。所以在以後的內容裡,指令及{{}}中的內容會被成為表示式。

  1. {{ number + 1 }}
  2. {{ ok ? 'YES' : 'NO' }}
  3. {{ message.split('').reverse().join('') }}
  4. <div v-bind:id="'list-' + id"></div>

上面的表示式都被支援。{{}}和指令中只支援一個表示式,不支援語句。如果想要使用語句,可以使用一會兒要講到的過濾器以及計算屬性。

注板表示式中試圖訪問使用者定義的全域性變數。意:模板表示式都被放在沙盒中,只能訪問全域性變數的一個白名單,如 Math 和 Date 。你不應該在模板表示式中試圖使用使用者自定義的全域性變數

2.3.3 過濾器

Vue.js過濾器被用作一些常見的文字格式化。過濾器應該被新增在 mustache 插值的尾部,由“管道符”指示:

{{message|capitalize}}

上面的例子使用了Vue.js內建的顧慮器,作用是使message的值首字母大寫。Vue.js也允許你自定義過濾器:

  1. new Vue({
  2. // ...
  3. filters: {
  4. becomeHappy: function (value) {
  5. return 'I am happy to say:' + value
  6. }
  7. }
  8. })

過濾器可以串聯,也可以接受引數。在接受引數時,第一個引數預設是前面返回的字串,第二個引數開始是使用者傳遞的引數,注意如果引數是字串要加引號。

{{message | filterA | filterB('string', somevar)}}

2.3.4 指令

指令(Directives)是帶有 v- 字首的特殊屬性。指令屬性的值預期是單一 JavaScript 表示式(除了 v-for)。指令的職責就是當其表示式的值改變時相應地將某些行為應用到 DOM 上。指令能夠實現條件渲染,列表渲染,繫結屬性等諸多功能。

下面是一個使用指令例子:

  1. <div id='app'><span v-if="condition" v-html="message"></span></div>
  2. var vm = {
  3. el:'#app',
  4. data:{
  5. condition: true,
  6. message: '<span style="color:red">Hello Vue!</span>'
  7. }
  8. }

瀏覽器顯示:

<span style="color:red">Hello Vue!</span>

v-if指令會根據vm.condition判斷是否渲染span,v-html指令會將message的內容以HTML的形式進行渲染。

有些指令接受一個“引數”,在指令後以冒號指出

<button v-bind:id="myBtn_id" v-on:click="sayHello"></button>

v-on用於指定事件,而v-bind用於繫結屬性,由於它們非常常見,所以Vue.js為它們提供看縮寫的形式:

<button :id="myBtn_id" @click="sayHello"></button>

sayHello為事件觸發的函式,函式寫在選項物件的methods屬性中。

修飾符(Modifiers)是以半形句號 . 指明的特殊字尾,置於指令引數的後面,=(如果存在)前面。用於指出一個指定應該以特殊方式繫結。例如,.prevent 修飾符告訴 v-on 指令對於觸發的事件呼叫

  1. <form v-on:submit.prevent="onSubmit"></form>
  2. <input v-model.trim="msg">
2.4 計算指令

在模板中表達式不宜過於複雜,可以使用計算指令講邏輯抽離出來。

2.4.1 基礎例子:

  1. <div id="example">
  2. <p>Original message: "{{ message }}"</p>
  3. <p>Computed reversed message: "{{ reversedMessage }}"</p>
  4. </div>
  5. var vm = new Vue({
  6. el: '#example',
  7. data: {
  8. message: 'Hello'
  9. },
  10. computed: {
  11. reversedMessage: function () {
  12. return this.message.split('').reverse().join('')
  13. }
  14. }
  15. })

渲染結果:

Original message: "Hello"

Computed reversed message: "olleH"。

計算屬性在選項物件的computed物件中編寫。該物件的屬性名即為需要計算得到的屬性名,值為一個匿名函式。但這並不意味著把這個匿名函式的值賦給該屬性(上例中的reversedMessage),事實上,在渲染的時候,該匿名函式會被執行,然後將return的值賦給computed物件的屬性。

2.4.2 計算setter

以上例中,reversedMessage依賴於vm.message屬性,並隨之變化。相當於我們為之建立了一個getter。 然而如果我們希望reversedMessage改變也會引起message的改變,則需要再為之建立一個setter:

  1. // ...
  2. computed: {
  3. fullName: {
  4. // getter
  5. get: function () {
  6. return this.firstName + ' ' + this.lastName
  7. },
  8. // setter
  9. set: function (newValue) {
  10. var names = newValue.split(' ')
  11. this.firstName = names[0]
  12. this.lastName = names[names.length - 1]
  13. }
  14. }
  15. }
  16. // ...

現在在執行 vm.fullName = 'John Doe' 時, setter 會被呼叫, vm.firstName 和 vm.lastName 也會被對應更新。

2.4.3 計算快取 vs Methods

<div>{{getFullName()}}</div>

你可能已經注意到我們可以通過呼叫表示式中的method來達到同樣的效果,與計算屬性的區別在於計算屬性是基於它的依賴快取的。只有當其依賴的資料發生變化時才會重新計算取值。相比而言,每當重新渲染時,method呼叫總會執行函式。

所以製作計時器的計劃會因此失敗

  1. computed: {
  2. now:function () {
  3. return new Date()
  4. }
  5. }

2.4.5 計算屬性 vs watcher

Vue.js提供了$watch,當制定資料變化是其中的相關函式會被呼叫,也可以起到計算屬性的效果。

  1. watch: {
  2. // 如果 question 發生改變,這個函式就會執行
  3. question: function (newQuestion) {
  4. this.answer = 'Waiting for you to stop typing...'
  5. this.getAnswer()
  6. }
  7. },

二者區別在於計算屬性將會在依賴的資料改變後立即發生變化,而watcher更適合處理非同步的情況,直到我們得到最終結果時,才設定中間狀態。

2.5 style與class

class和style都是屬性,可以使用v-bind指令進行繫結,Vue.js加強了它們。表示式的結果除了可以是字串外,還可以是陣列或物件。

2.5.1 class

v-bind指令不影響原有的class。

(1)物件語法

<div :class="{active:condition}"></div>

active是一個class的名稱,而condition則是一個表示式,當condition為true的時候,class將被執行渲染。

你也可以直接傳一個表示式:

  1. <div v-bind:class="classObject"></div>
  2. ...
  3. data: {
  4. classObject: {
  5. active: true,
  6. 'text-danger': false
  7. }
  8. }
  9. ...

(2)陣列語法

  1. <div v-bind:class="[activeClass, errorClass]">
  2. data: {
  3. activeClass: 'active',
  4. errorClass: 'text-danger'
  5. }

與物件語法不同,陣列語法中元素全部為表示式。你也可以將表示式設定為物件

<div v-bind:class="[{ active: isActive }, errorClass]">

2.5.2 style

這裡css屬性名支援中劃線命名法及駝峰命名法。

(1)物件語法

  1. <div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
  2. data: {
  3. activeColor: 'red',
  4. fontSize: 30
  5. }

物件的屬性是css屬性名,值是表示式的返回值。當然推薦你把表示式物件抽離出來

(2)陣列語法

v-bind:style 的陣列語法可以將多個樣式物件應用到一個元素上,每個元素都是一個返回CSS物件的表示式。

<div v-bind:style="[baseStyles, overridingStyles]">

(3)自動新增字首

當 v-bind:style 使用需要特定字首的 CSS 屬性時,如 transform ,Vue.js 會自動偵測並新增相應的字首。

2.6 條件渲染

2.6.1 v-if/v-else

vue.js把v-if指令的功能抽離出來,只用來判斷DOM元素是否進行渲染。

<h1 v-if="ok">Yes</h1>

v-if指令不能作用於根元素,否則會給出警告並報錯。

可以使用v-else指令設定不滿足條件的話將做什麼,v-else必須緊跟v-if(或者後面提到的v-show),否則無法被識別。

  1. <h1 v-if="ok">Yes</h1>
  2. <h1 v-else>No</h1>

v-if是惰性的,在第一次條件為真的時候才進行渲染。

2.6.2 template

子元素還好應付,如果有若干個同級元素需要根據條件進行判斷是否渲染,則需要使用template

  1. <template v-if="ok">
  2. <h1>Title</h1>
  3. <p>Paragraph 1</p>
  4. <p>Paragraph 2</p>
  5. </template>

template本身不會被渲染成DOM節點。

2.6.3 v-show

v-show是在會被渲染成DOM,若其後表示式的值為假,則會在渲染時加上style="display:none"。由於其總是會被渲染,所以v-show可以被繫結到根結點上。同時,Vue.js規定v-show不能作用於template。顯然,v-show更適合頻繁切換的情況。

  1. <p v-show="okay">okay</p>
  2. <p v-show="!okay">not okay</p>
2.7 列表渲染

2.7.1 迭代陣列

最基本的渲染形式是對陣列的處理:

  1. <ul>
  2. <li v-for="student in students">{{student.name}}</li>
  3. </ul>
  4. students: [{name: 'Jack', age: 15},
  5. {name: 'Tom', age: 15},
  6. {name: 'LiMing', age: 15}]

2.7.2 迭代物件

  1. <ul>
  2. <li v-for="value in person">{{value}}</li>
  3. </ul>
  4. ... ...
  5. data: {
  6. person:{
  7. name:"Jack",
  8. age:17
  9. }
  10. }

2.7.3 資料訪問許可權

在 v-for 塊中,我們擁有對父作用域及當前作用域屬性的完全訪問許可權。

  1. <ul>
  2. <li v-for="person in persons">
  3. {{person.name}}
  4. <span v-html="person.html"></span>
  5. </li>
  6. </ul>

2.7.4 template

如同 v-if 模板,你也可以用帶有 v-for 的 <template> 標籤來渲染多個同級元素塊。

2.7.5 key(鍵名)與index

你可以提供索引和鍵名作為引數

<div v-for="(value[ ,key[,index]]) in object">{{index}}.{{value}}</div>

$Index和$key在Vue.js2.0中已經被淘汰

2.7.6 迭代整數

此外,v-for還可以迭代整數

  1. <div>
  2. <span v-for="n in 10">{{ n }}</span>
  3. </div>

輸出1至10

2.7.8 使用key幫Vue一個小忙

重新渲染一個單獨的值,比如message對Vue來說是小菜一碟。但如果當列表裡的某一個值被改變,需要重新渲染整個列表則是不可接受的。

當 Vue.js 用 v-for 正在更新已渲染過的元素列表時,它預設用 “就地複用” 策略。如果資料項的順序被改變,而不是移動 DOM 元素來匹配資料項的順序, Vue 將簡單複用此處每個元素,並且確保它在特定索引下顯示已被渲染過的每個元素。

我們為列表中每個元素提供一個key以幫助Vue.js跟蹤每個節點的身份,從而重用和重新排序現有元素。

  1. <div v-for="student in students" :key="student.student_id">
  2. <!-- 內容 -->
  3. </div>
  4. data: {
  5. students: [{student_id:100100,name:'Jack'}, {student_id:'100102', name: 'Tom'}]
  6. }

2.7.9 陣列重新渲染

Vue 包含一組觀察陣列的變異方法,所以它們也將會觸發檢視更新。這些方法如下:

  1. push()
  2. pop()
  3. shift()
  4. unshift()
  5. splice()
  6. sort()
  7. reverse()

你開啟控制檯,然後用前面例子的 items 陣列呼叫突變方法:

example1.items.push({ message: 'Baz' }) 

對於諸如filter(), concat(), slice()等非變異方法,替換掉整個陣列即可。Vue 實現了一些智慧啟發式方法來最大化 DOM 元素重用,所以用一個含有相同元素的陣列去替換原來的陣列是非常高效的操作。

不過換個思路,如果我不希望真正改變陣列的順序或者值,可以使用計算屬性或Methods實現

2.7.9 陣列渲染時的缺陷與解決辦法

由於 JavaScript 的限制, Vue 不能檢測以下變動的陣列:

  1. 當你直接設定一個項的索引時,例如: vm.items[indexOfItem] = newValue
  2. 當你修改陣列的長度時,例如: vm.items.length = newLength

Vue也提供瞭解決問題的辦法,解決第一個問題:

  1. // Vue.set
  2. Vue.set(example1.items, indexOfItem, newValue)
  3. // Array.prototype.splice`
  4. example1.items.splice(indexOfItem, 1, newValue)

解決第二個問題:

example1.items.splice(newLength)
2.8 事件監聽器

2.8.1 內聯監聽器

可以為事件監聽器傳遞引數,如果需要傳遞事件event物件,則寫成$event的形式

  1. <button v-on:click="warn('Form cannot be submitted yet.', $event)">Submit</button>
  2. ...
  3. methods:{warn:function (message, event) {... ...}}
  4. ...

2.8.2 在HTML上繫結事件?!

你可能注意到這種事件監聽的方式違背了關注點分離(separation of concern)傳統理念。不必擔心,因為所有的 Vue.js 事件處理方法和表示式都嚴格繫結在當前檢視的 ViewModel 上,它不會導致任何維護上的困難。實際上,使用 v-on 有幾個好處:

  1. 掃一眼 HTML 模板便能輕鬆定位在 JavaScript 程式碼裡對應的方法。

  2. 因為你無須在 JavaScript 裡手動繫結事件,你的 ViewModel 程式碼可以是非常純粹的邏輯,和 DOM 完全解耦,更易於測試。

  3. 當一個 ViewModel 被銷燬時,所有的事件處理器都會自動被刪除。你無須擔心如何自己清理它們。

2.8.3 事件修飾符

Vue提供的事件修飾符將常見的事件設定(比如阻止元素預設事件,或阻止事件冒泡)旨在讓我們的Methods更加關注資料邏輯。通過由點(.)表示的指令字尾來呼叫修飾符。

<a v-on:click.stop="doThis"></a>

常見的事件修修飾符有以下幾個:

  1. .stop // 阻止事件冒泡
  2. .prevent // 阻止元素預設事件
  3. .capture // 使用事件捕獲模式監聽事件
  4. .self //只當事件在該元素本身(而不是子元素)觸發時觸發回撥

事件修飾符可以串聯使用:

<a v-on:click.stop.prevent="doThat"></a>

2.8.4 按鍵修飾符

修飾符中還有一種按鍵修飾符,其值是鍵盤按鍵的keycode或者預先定義好的keycode別名,例如:

  1. <input v-on:keyup.13="submit">
  2. <input v-on:keyup.enter = "submit">

當按下回車鍵時,執行submit。

下面是全部的按鍵別名:

  1. enter
  2. tab
  3. delete (捕獲 “刪除” 和 “退格” 鍵)
  4. esc
  5. space
  6. up
  7. down
  8. left
  9. right

我們也可以為按鍵自定義別名:

  1. // 此時我們就可以通過使用@keyup.f1代替@keyup.112
  2. Vue.config.keyCodes.f1 = 112
2.9 表單控制元件繫結

你可以用 v-model 指令在表單控制元件元素上建立雙向資料繫結,但其本質上不過是語法糖。

最基本的例子:

<TextArea v-model="message" placeholder="edit me">
作者: 聖經的旋律 連結:http://www.imooc.com/article/14438來源:慕課網