0%

[Vue]Vue Directive

前情提要

前一篇已介紹了Vue基本語法,筆者相信應該是有辦法撰寫簡單的邏輯,接下來這一篇介紹v開頭directive相關技巧及知識,筆者使用工具及環境參考上一篇[Vue]Vue基本語法

內容

v開頭directive

v-html

若我們的資料是包含html tag,且是要當作html語法輸出時如何做呢?會用到v-html這個directive。

Html部份

1
2
<p>Using mustaches: {{ rawHtml }}</p>
<p>Using v-html directive: <span v-html="rawHtml"></span></p>

效果如下

Using mustaches: <span style="color: red">This should be red.</span>

Using v-html directive: This should be red.

以上,有套用v-html屬性才會當作html語法輸出。

v-if

若我們有一些顯示區域是需要透過資料綁定及動態設定出現與否,則需透過v-if這個directive,可搭配使用 v-else v-else-if,可以在vue編譯時期就會去除符合條件之區塊。

Html部份

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

以上,使用ok這個參數來控制h1區塊顯示與否

v-show

v-if一樣,v-show亦是控制顯示區域出現與否,只是在於v-show是使用html的style屬性display控制顯示或隱藏。

v-if Vs v-show 若template一次性的顯示與否可以透過v-if 若是頻繁變動顯示隱藏邏輯則透過v-show控制會使效能更好

以上,筆者稍微要再解釋一下,頻繁變動顯示隱藏邏輯這個狀況,可以想像一下,若套用v-if來控制的話,表示vue會在判斷到需隱藏時實際將dom元素移除,需顯示時將dom元素重新插入。dom操作效能問題參考 dom操作與優化探討,因此最好不要因自己寫的邏輯觸發頻繁操作dom而造成效能瓶頸。

v-for

這個directive就是大家會經常用到的,頁面上經常會將撈到的資料利用tableul>li來呈現出來,最簡單的例子就是menu的顯示,查詢結果呈現。

Html部份

1
2
3
4
5
<ul id="example-1">
<li v-for="item in items">
{{ item.message }}
</li>
</ul>

Javascript部份

1
2
3
4
5
6
7
8
9
var example1 = new Vue({
el: '#example-1',
data: {
items: [
{ message: 'Foo' },
{ message: 'Bar' }
]
}
})

效果如下

  • Foo
  • bar

使用方法

v-for支援陣列及物件,詳細資訊如下

  • v-for陣列部份
1
2
3
<div v-for="item in items"></div>
<!-- 可倒出陣列順序編號 -->
<div v-for="(item, index) in items"></div>
  • v-for物件部份
1
2
3
4
5
6
<!-- 將各屬性值依序印出 -->
<div v-for="value in obj"></div>
<!-- key為屬性名稱 -->
<div v-for="(value, key) in obj"></div>
<!-- index為屬性順序編號 -->
<div v-for="(value, key, index) in obj"></div>

v-for中盡可能設定key屬性

v-for中很重要的觀念是,vue有提供key屬性可以設定各item的識別欄位,使vue追縱更快速 參考,因此筆者建議若每筆資料包含識別欄位則使用v-bind設定key屬性上去。

1
2
3
<div v-for="item in items" :key="item.id">
<!-- content -->
</div>

變更偵測原理

陣列相關的操作/物件屬性值變更皆會使Vue重繪

官網上面還有提到陣列或物件變更偵測的機制,基本上變更偵測邏輯很容易理解

  • 陣列變更偵測邏輯

    • 陣列相關的操作
      1
      2
      3
      4
      5
      6
      7
      push()
      pop()
      shift()
      unshift()
      splice()
      sort()
      reverse()
  • 物件變更偵測邏輯

    • 物件屬性值變更

變更偵測注意事項

變更偵測注意事項請參考以下說明

  • 陣列變更偵測注意事項
    陣列相關變更偵測因javascript限制,除非是陣列的操作,若使用
    1
    2
    3
    4
    // 針對某一筆資料的指定新的值
    vm.items[indexOfItem] = newValue
    // 重新指定陣列長度
    vm.items.length = newLength
    • 解決方式
      針對以上的第一個問題,vue也提供變相的解法,需透過vm.set來通知變更
      1
      2
      // Vue.set
      Vue.set(vm.items, indexOfItem, newValue)
      或者使用javascriptArray技巧 參考
      1
      2
      // 將某一個位置的值使用newValue代替
      vm.items.splice(itemIndex, 1, newValue)
      針對第二個問題可使用Array技巧Splice來解
      1
      vm.items.splice(newLength)
  • 物件變更偵測注意事項
    基本上跟陣列雷同,物件動態新增屬性會使Vue無法偵測變更
    1
    2
    3
    4
    5
    6
    7
    8
    9
    var vm = new Vue({
    data: {
    a: 1
    }
    })
    // `vm.a` 設定newValue可以被偵測變更

    vm.b = 2
    // `vm.b` 設定newValue則無法被偵測變更
    與陣列一樣的解法,需透過vm.set的方式
    1
    Vue.set(vm.userProfile, 'age', 27)

可搭配使用說明

Range

我可以直接指定一個數字當作數值範圍結束值,透過v-for產生指定範圍內的數值

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

可使用於template

1
2
3
4
5
6
<ul>
<template v-for="item in items">
<li>{{ item.msg }}</li>
<li class="divider" role="presentation"></li>
</template>
</ul>
v-if

v-for同階層,再加上v-if來過濾資料,等於符合v-if中宣告條件才會被印出

1
2
3
<li v-for="todo in todos" v-if="!todo.isComplete">
{{ todo }}
</li>

結論

筆者經驗來說,v-html非常少使用,除非撰寫的是CMS相關系統,才需將使用者輸入及設定之html語法原始地呈現於畫面上。v-if、v-show會交替使用,選擇參考內文中比較,v-for最常使用,無論是將下拉式選單資料來源綁定於option中,Menu選單動態呈現,將查詢結果顯示於table中,但可以發現vue的directive不複雜,非常容易使用,那你還等什麼呢?