Vue.js基礎拾遺

冷星1024發表於2019-03-19

模版語法

插值

1、Vue.js的資料繫結形式是使用“Mustache”語法(雙大括號)的形式,針對Html程式碼,需要使用v-html指令。

<p>Using v-html directive: <span v-html="rawHtml"></span></p>
複製程式碼

2、Mustache語法不能作用在HTML特性上面,此時需要使用v-bind指令。

<div v-bind:id="dynamicId"></div>
複製程式碼

指令

1、一些指令能夠接收一個“引數”,在指令名稱之後以冒號表示,如v-bind

<a v-bind:href="url">...</a>
複製程式碼

2、從2.6.0開始,可以用方括號擴起來的Javascript表示式作為一個指令的引數

<a v-bind:[attributeName]='url'>...</a>
複製程式碼

這裡的 attributeName 會被作為一個 JavaScript 表示式進行動態求值,求得的值將會作為最終的引數來使用。例如,如果你的 Vue 例項有一個 data 屬性 attributeName,其值為 "href",那麼這個繫結將等價於 v-bind:href。

同樣,我們可以使用動態引數為一個動態的事件名繫結處理函式

<a v-on:[eventName]="doSomething"> ... </a>
複製程式碼

動態引數預期會求出一個字串,異常情況下值為 null。這個特殊的 null 值可以被顯性地用於移除繫結。任何其它非字串型別的值都將會觸發一個警告。 動態參數列達式有一些語法約束,因為某些字元,例如空格和引號,放在 HTML 特性名裡是無效的。

3、修飾符(modifier)是以半形句號.指明的特殊字尾,用於指出一個指令應該以特殊方式繫結。如.prevent修飾符告訴v-on指令對於觸發的事件呼叫event.prevent

<form v-on:submit.prevent="onSubmit">...</form>
複製程式碼

4、指令簡寫

v-bind指令

<!-- 完整語法 -->
<a v-bind:href="url">...</a>

<!-- 縮寫 -->
<a :href="url">...</a>
複製程式碼

v-on指令

<!-- 完整語法 -->
<a v-on:click="doSomething">...</a>

<!-- 縮寫 -->
<a @click="doSomething">...</a>
複製程式碼

計算屬性與偵聽器

計算屬性是和普通屬性一樣在模版中繫結的,只不過該屬性的值涉及到一系列的計算,並不是單純的一個屬性值。

計算屬性的getter函式是沒有副作用(side effect)的。

計算屬性VS方法

我們可以將同一個函式定義為一個方法而不是一個計算屬性,兩種方式的最終結果是相同的。不同的是計算屬性是基於他們的依賴進行快取的。當相關依賴不變的情況下,計算屬性是直接獲取快取的結果,不需要執行函式,而方法的寫法每當重新渲染時,都會被再次執行。

計算屬性VS偵聽屬性

Vue提供了一種更通用的方式來觀察和響應Vue例項上的資料變更:偵聽屬性,通過watch來監聽屬性的變化。但是通常更好的做法是使用計算屬性而不是命令式的watch回撥。

那麼什麼時候選擇偵聽屬性更好呢?

當響應資料變化的處理是執行非同步或者開銷較大的操作時,使用偵聽屬性是有用的。

Class與Style繫結

v-bind用於classstyle時,Vue.js做了專門的增強,表示式結果的型別除了字串之外,還可以是物件或陣列。

繫結HTML Class

1、v-bind:class指令可以與普通的class屬性共存。我們也可以繫結一個返回物件的計算屬性,這是非常有用的模式。

2、我們可以把一個陣列傳給v-bind:class,以應用一個class列表。

3、當在一個自定義元件上使用 class 屬性時,這些類將被新增到該元件的根元素上面。這個元素上已經存在的類不會被覆蓋。

繫結內聯樣式

1、v-bind:style 的物件語法十分直觀——看著非常像 CSS,但其實是一個 JavaScript 物件。CSS 屬性名可以用駝峰式 (camelCase) 或短橫線分隔 (kebab-case,記得用單引號括起來) 來命名.

2、直接繫結到一個樣式物件通常更好,這會讓模板更清晰:

3、物件語法常常結合返回物件的計算屬性使用

4、當 v-bind:style 使用需要新增瀏覽器引擎字首的 CSS 屬性時,如 transform,Vue.js 會自動偵測並新增相應的字首。

5、可以為 style 繫結中的屬性提供一個包含多個值的陣列,常用於提供多個帶字首的值。這樣只會渲染陣列中最後一個被瀏覽器支援的值。

條件渲染

1、v-if 指令用於條件性地渲染一塊內容。這塊內容只會在指令的表示式返回 truthy 值的時候被渲染。也可以用 v-else 新增一個“else 塊”。v-else 元素必須緊跟在帶 v-if 或者 v-else-if 的元素的後面,否則它將不會被識別。

2、在 <template> 元素上使用 v-if 條件渲染分組

3、通過新增一個具有唯一值的 key 屬性來表達“兩個元素是完全獨立的,不要複用他們”。

4、帶有 v-show 的元素始終會被渲染並保留在 DOM 中。v-show 只是簡單地切換元素的 CSS 屬性 display

v-if & v-show

v-if 是“真正”的條件渲染,因為它會確保在切換過程中條件塊內的事件監聽器和子元件適當地被銷燬和重建。

v-if 也是惰性的:如果在初始渲染時條件為假,則什麼也不做——直到條件第一次變為真時,才會開始渲染條件塊。

相比之下,v-show 就簡單得多——不管初始條件是什麼,元素總是會被渲染,並且只是簡單地基於 CSS 進行切換。

一般來說,v-if 有更高的切換開銷,而 v-show 有更高的初始渲染開銷。因此,如果需要非常頻繁地切換,則使用 v-show 較好;如果在執行時條件很少改變,則使用 v-if 較好。

5、當 v-ifv-for 一起使用時,v-for 具有比 v-if 更高的優先順序。

列表渲染

1、v-for 指令根據一組陣列的選項列表進行渲染。v-for 指令需要使用 item in items 形式的特殊語法,items 是源資料陣列並且 item 是陣列元素迭代的別名。

2、可以用 of 替代 in 作為分隔符,因為它是最接近 JavaScript 迭代器的語法, v-for="item of items"

3、可以用v-for來迭代一個物件的屬性。v-for="(value, key) in object"

在遍歷物件時,是按 Object.keys() 的結果遍歷,但是不能保證它的結果在不同的 JavaScript 引擎下是一致的。

4、為了給 Vue 一個提示,以便它能跟蹤每個節點的身份,從而重用和重新排序現有元素,你需要為每項提供一個唯一 key 屬性。理想的 key 值是每項都有的唯一 id

不要使用物件或陣列之類的非原始型別值作為 v-for 的 key。用字串或數型別的值取而代之。

5、由於Javascript的限制,Vue不能檢測到下面的變動情況:

  • 當利用索引直接設定一個專案時,不會觸發狀態更新。可以通過下面方式實現:
// Vue.set
Vue.set(vm.items, indexOfItem, newValue)
// Array.prototype.splice
vm.items.splice(indexOfItem, 1, newValue)
// 使用 vm.$set 例項方法,該方法是全域性方法 Vue.set 的一個別名 
vm.$set(vm.items, indexOfItem, newValue)
複製程式碼
  • 當直接修改陣列長度時,不會觸發狀態更新。可以通過下面方式實現:
vm.items.splice(newLength)
複製程式碼

6、Vue 不能檢測物件屬性的新增或刪除

對於已經建立的例項,Vue 不能動態新增根級別的響應式屬性。但是,可以使用 Vue.set(object, key, value) 方法向巢狀物件新增響應式屬性

7、需要為已有物件賦予多個新屬性,比如使用 Object.assign() 或 _.extend()。在這種情況下,你應該用兩個物件的屬性建立一個新的物件。

// ❌
Object.assign(vm.userProfile, {
  age: 27,
  favoriteColor: 'Vue Green'
})

// ✅
vm.userProfile = Object.assign({}, vm.userProfile, {
  age: 27,
  favoriteColor: 'Vue Green'
})
複製程式碼

8、顯示過濾/排序結果,可以通過建立返回過濾或排序陣列的計算屬性來實現。在計算屬性不適用的情況下(如巢狀v-for迴圈中)可以適用method方法來處理。

9、v-for & v-if

當它們處於同一節點,v-for 的優先順序比 v-if 更高,這意味著 v-if 將分別重複執行於每個 v-for 迴圈中。

10、在自定義元件裡,你可以像任何普通元素一樣用 v-for

2.2.0+ 的版本里,當在元件中使用 v-for 時,key 現在是必須的。

然而,任何資料都不會被自動傳遞到元件裡,因為元件有自己獨立的作用域。為了把迭代資料傳遞到元件裡,我們要用 props

// 一個完整的todolist demo
<div id="todo-list-example">
  <form v-on:submit.prevent="addNewTodo">
    <label for="new-todo">Add a todo</label>
    <input
      v-model="newTodoText"
      id="new-todo"
      placeholder="E.g. Feed the cat"
    >
    <button>Add</button>
  </form>
  <ul>
    <li
      is="todo-item"
      v-for="(todo, index) in todos"
      v-bind:key="todo.id"
      v-bind:title="todo.title"
      v-on:remove="todos.splice(index, 1)"
    ></li>
  </ul>
</div>

Vue.component('todo-item', {
  template: '\
    <li>\
      {{ title }}\
      <button v-on:click="$emit(\'remove\')">Remove</button>\
    </li>\
  ',
  props: ['title']
})

new Vue({
  el: '#todo-list-example',
  data: {
    newTodoText: '',
    todos: [
      {
        id: 1,
        title: 'Do the dishes',
      },
      {
        id: 2,
        title: 'Take out the trash',
      },
      {
        id: 3,
        title: 'Mow the lawn'
      }
    ],
    nextTodoId: 4
  },
  methods: {
    addNewTodo: function () {
      this.todos.push({
        id: this.nextTodoId++,
        title: this.newTodoText
      })
      this.newTodoText = ''
    }
  }
})

複製程式碼

事件處理

事件修飾符

  • .stop
  • .prevent
  • .capture
  • .self
<!-- 阻止單擊事件繼續傳播 -->
<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>

複製程式碼

使用修飾符時,順序很重要;相應的程式碼會以同樣的順序產生。因此,用 v-on:click.prevent.self 會阻止所有的點選,而 v-on:click.self.prevent 只會阻止對元素自身的點選。

  • .once(2.1.4 new)
<!-- 點選事件將只會觸發一次 -->
<a v-on:click.once="doThis"></a>
複製程式碼

不像其它只能對原生的 DOM 事件起作用的修飾符,.once 修飾符還能被用到自定義的元件事件上。

  • .passive(2.3.0 new)
<!-- 滾動事件的預設行為 (即滾動行為) 將會立即觸發 -->
<!-- 而不會等待 `onScroll` 完成  -->
<!-- 這其中包含 `event.preventDefault()` 的情況 -->
<div v-on:scroll.passive="onScroll">...</div>  // 2.3.0 new
複製程式碼

.passive 修飾符尤其能夠提升移動端的效能

不要把 .passive 和 .prevent 一起使用,因為 .prevent 將會被忽略,同時瀏覽器可能會向你展示一個警告。請記住,.passive 會告訴瀏覽器你不想阻止事件的預設行為。

按鍵修飾符

在監聽鍵盤事件時,我們經常需要檢查詳細的按鍵。Vue 允許為 v-on 在監聽鍵盤事件時新增按鍵修飾符

<!-- 只有在 `key` 是 `Enter` 時呼叫 `vm.submit()` -->
<input v-on:keyup.enter="submit">
複製程式碼

Vue提供了常用的按鍵碼的別名

  • .enter
  • .tab
  • .delete (捕獲“刪除”和“退格”鍵)
  • .esc
  • .space
  • .up
  • .down
  • .left
  • .right

系統修飾鍵(2.1.0 new)

可以用如下修飾符來實現僅在按下相應按鍵時才觸發滑鼠或鍵盤事件的監聽器。

  • .ctrl
  • .alt
  • .shift
  • .meta

請注意修飾鍵與常規按鍵不同,在和 keyup 事件一起用時,事件觸發時修飾鍵必須處於按下狀態。換句話說,只有在按住 ctrl 的情況下釋放其它按鍵,才能觸發 keyup.ctrl。而單單釋放 ctrl 也不會觸發事件。如果你想要這樣的行為,請為 ctrl 換用 keyCode:keyup.17。

.exact修飾符(2.5.0 new)

.exact 修飾符允許你控制由精確的系統修飾符組合觸發的事件。

<!-- 即使 Alt 或 Shift 被一同按下時也會觸發 -->
<button @click.ctrl="onClick">A</button>

<!-- 有且只有 Ctrl 被按下的時候才觸發 -->
<button @click.ctrl.exact="onCtrlClick">A</button>

<!-- 沒有任何系統修飾符被按下的時候才觸發 -->
<button @click.exact="onClick">A</button>
複製程式碼

滑鼠按鈕修飾符(2.2.0 new)

  • .left
  • .right
  • .middle

這些修飾符會限制處理函式僅響應特定的滑鼠按鈕。

表單輸入繫結

你可以用 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 作為事件。

對於需要使用輸入法 (如中文、日文、韓文等) 的語言,你會發現 v-model 不會在輸入法組合文字過程中得到更新。如果你也想處理這個過程,請使用 input 事件。

修飾符

.lazy

在預設情況下,v-model 在每次 input 事件觸發後將輸入框的值與資料進行同步 (除了上述輸入法組合文字時)。你可以新增 lazy 修飾符,從而轉變為使用 change 事件進行同步:

<!-- 在“change”時而非“input”時更新 -->
<input v-model.lazy="msg" >
複製程式碼

.number

如果想自動將使用者的輸入值轉為數值型別,可以給 v-model 新增 number 修飾符:

<input v-model.number="age" type="number">
複製程式碼

這通常很有用,因為即使在 type="number" 時,HTML 輸入元素的值也總會返回字串。如果這個值無法被 parseFloat() 解析,則會返回原始的值。

.trim

如果要自動過濾使用者輸入的首尾空白字元,可以給 v-model 新增 trim 修飾符:

<input v-model.trim="msg">
複製程式碼

元件基礎

因為元件是可複用的 Vue 例項,所以它們與 new Vue 接收相同的選項,例如 data、computed、watch、methods 以及生命週期鉤子等。僅有的例外是像 el 這樣根例項特有的選項。

1、data必須是函式

一個元件的data選項必須是一個函式,因此每個例項才可以維護一份被返回物件的獨立的拷貝。

2、元件有兩種註冊型別:全域性註冊區域性註冊。我們的元件都只是通過Vue.component全域性註冊的

Vue.component('my-component-name', {
  // ... options ...
})
複製程式碼

全域性註冊的元件可以用在其被註冊之後的任何 (通過 new Vue) 新建立的 Vue 根例項,也包括其元件樹中的所有子元件的模板中。

3、通過Prop向子元件傳遞資料

Prop 是你可以在元件上註冊的一些自定義特性。當一個值傳遞給一個 prop 特性的時候,它就變成了那個元件例項的一個屬性。一個元件預設可以擁有任意數量的 prop,任何值都可以傳遞給任何 prop。

4、每個元件必須只有一個根元素

5、父級元件可以像處理 native DOM 事件一樣通過 v-on 監聽子元件例項的任意事件,同時子元件可以通過呼叫內建的 $emit 方法 並傳入事件名稱來觸發一個事件:

<parentElement 
  ...
  v-on:special-event="todo something..."></parentElement>

<childElement v-on:click="$emit('special-event')">
  Click to trigger special-enent
</childElement>
複製程式碼

插槽

Vue自定義的<slot>元素可以實現通過插槽分發內容。

解析DOM時的注意事項

HTML元素有些會有嚴格的限制包含和被包含的關係,這會導致我們使用一些有約束條件的元素時會遇到一些問題。此時可以通過is特性來解決

<table>
  <tr is="blog-post-row"></tr>
</table>
複製程式碼

下面情況不會出現限制:

  • 字串模版(例如 template:‘...’)
  • 單檔案元件(.vue)
  • <script type="text/x-template">

小結

以上是在重溫Vue.js官方文件基礎部分內容時做出的拾遺筆記,記錄認為是一些需要特別注意的地方。後續會繼續深入進行Vue.js的學習。

相關文章