【Vue】經過自定義指令回顧 v-內置指令

Vue.js 的各類指令(Directives)更加方便咱們去數據驅動 DOM,例如 v-bind、v-on、v-model、v-if、v-for、v-once 等內置指令,這些指令的職責就是當表達式改變時將某些行爲應用到 DOM 上,儘可能不去操做增刪改 DOM。經過了解如何去自定義指令,能夠想象內置指令是如何完成的。

1、自定義指令

在須要特殊功能時,使用自定義指令對 DOM 進行底層操做vue

1.1 註冊

自定義指令的註冊分爲全局註冊局部註冊,相似組件的註冊,只是方法名爲 directive,寫法以下:node

// 全局註冊 自定義指令
Vue.directive(‘mydir’,{
    // 指令選項
});
// 全局註冊 自定義指令函數
Vue.directive('mydir', function () {
  // 這裏將會被 `bind` 和 `update` 調用
})
// 局部註冊(只針對組件內元素)
export default {
    directives: {
        mydir: {
            // 指令選項
        }
    }
}
須要注意的是: Vue.directive( ) 註冊指令要在實例初始化 new Vue( ) 以前才能全局註冊指令。定義指令時駝峯式寫法會報錯,因此通常小寫。

1.2 指令選項

自定義指令的選項是由幾個鉤子函數(可選)組成,能夠根據需求選擇不一樣的鉤子,例如使用全局註冊一個指令時:express

Vue.directive('mydir', {
  bind: function () {
    // 只調用一次,指令第一次綁定到元素時調用,用於在綁定元素時執行一次的初始化動做。
    },
  update: function () {
    // 第一次是緊跟在 bind 以後調用,得到的參數是綁定的初始值,
    // 以後被綁定元素所在的模板更新時調用,而不論綁定值是否變化,能夠忽略沒必要要的模板更新。    
    },  
  inserted: function () {
    // 被綁定元素插入父節點時調用(父節點存在便可調用,沒必要存在於 document 中)。
    },
  componentUpdated: function () {
    // 被綁定元素所在模板完成一次更新週期時調用。
    },
  unbind: function () {
    // 只調用一次, 指令與元素解綁時調用。
    }
})

以上每一個鉤子函數都有幾個參數可用:數組

  • el:指令所綁定的元素,能夠用來直接操做 DOM;
  • binding:包含指令信息的一個對象;
  • vnode:Vue 編譯的生成虛擬節點;
  • oldVnode:上一次的虛擬節點,僅在update和componentUpdated鉤子函數中可用。

1.3 示例

// 一個帶自定義指令的元素
<div v-mytest:foo.m1.m2="1+1">MyDirective</div>

// 部分 JS 代碼
export default {
    directives:{
      mytest: {
        bind: function (el, binding, vnode) {
          console.log(el)
          console.log(binding)
          console.log(vnode)
        }
      }
    }
}

控制檯輸出截圖:
clipboard.pngsvg

其中對於 binding 對象輸出的屬性有:函數

  • rawName: "v-mytest:foo.m1.m2" // 自定義指令
  • name: "mytest" // 指令名稱
  • arg: "foo" // 指令的參數
  • modifiers: {m1: true, m2: true} // 指令的修飾符
  • expression: "1+1" // 指令綁定值的字符串形式
  • value: 2 // 指令的綁定值

2、v-bind || : 綁定屬性

Vue 內置指令 v-bind 用於動態更新 HTML 元素屬性,使用 v-bind:someAttr = "someData"或者語法糖 :someAttr = "someData"就能夠在 someData 改變時更新綁定的 someAttr 屬性。測試

2.1 基本用法

綁定單一的屬性值this

<a :href="url" :id="linkID">連接</a>

測試 data 以下:url

// js
data : {
    url: 'https://www.baidu.com/',
    linkID : 'myid'
}

元素渲染輸出:
<a href="https://www.baidu.com/" id="myid">連接</a>spa

2.2 對象語法

v-bind 最經常使用的是綁定 class 或 style 屬性來動態改變樣式。例如能夠給 :class 設置一個對象來動態切換 class 的值:

<!-- class 綁定 -->
<div :class="{colorRed: isRed}"></div>

當 isRed:true 時渲染輸出:
<div class="colorRed"></div>

對象中能夠傳入多個屬性值來動態切換 class:

<!-- class 綁定,傳入多個屬性 -->
<div :class="{ classA: isA, classB: isB }">

當 isA、isB 變化時 classA、classB 會動態更新,當都爲 true 時顯然渲染結果爲:
<div class="classA classB"></div>

同理對於 style 能夠傳入對象屬性,而且可使用字符串拼接:

<!-- style 綁定 -->
<div :style="{ fontSize: size + 'px' }"></div>

對於元素中的各個對象能夠統一用 v-bind 綁定:

<!-- 綁定一個有屬性的對象 -->
<div v-bind="{ id: someProp, 'other-attr': otherProp }"></div>

2.3 數組語法

class 能夠傳入多值,給 :class 綁定一個數組就可使用 class 列表

<div :class="[activeA, activeB]"></div>

例如當 {activeA: 'class1', activeB: 'class2'} 時渲染結果爲:
<div class="class1 class2"></div>

還能夠在數組語法中使用三元表達式切換 class,例如:

<div :class="[isA ? activeA : '', activeB]">

在 class 有多個條件時使用三元表達式比較繁瑣,能夠在數組語法中使用對象語法

<div :class="[{activeA: isA}, activeB]">

2.4 修飾符

v-bind 的修飾符不多,API 中只提供.prop.camel.sync,而且多用於組件,使用方式示例:

<!-- 經過 prop 修飾符綁定 DOM 屬性 (property) -->
<div v-bind:text-content.prop="text"></div>

<!-- .camel 修飾符(2.1.0+)將 v-bind 屬性名稱 kebab-case 駝峯化爲 camelCase -->
<svg :view-box.camel="viewBox"></svg>

<!-- .sync 修飾符(2.3.0+) 語法糖,會擴展成一個更新父組件綁定值的 v-on 偵聽器-->
<text-document v-bind:title.sync="doc.title"></text-document>
<!-- 批量綁定,將 doc 對象中的每個屬性 (如 title) 都做獨立的 prop ,各自添加 v-on 監聽器-->
<text-document v-bind.sync="doc"></text-document>

3、v-on || @ 監聽事件

v-on 用於動態綁定事件監聽器,使用 v-on:someEvent = "someFunction"或者語法糖 @someEvent = "someFunction"就能夠監聽 someEvent 進行交互。

3.1 基本用法

@someEvent 調用的方法名後面能夠不跟(),例如:

<a :href="url" :id="linkID">連接</a>
<!-- 監聽一個事件 -->
<button @click="changeFun">change button</button>

能夠在 methods 中添加函數:

// 部分 JS 代碼
methods :{
  changeFun : function () {
    this.linkID = 'changeID' // 指向當前組件自己
  }
}

點擊 button 按鈕後 a 元素的 id 改變:
<a href="https://www.baidu.com/" id="changeID">連接</a>

固然 v-on 還可使用對象語法監聽多個事件:

<!-- v2.4.0+ -->
<button v-on="{ mousedown: doThis, mouseup: doThat }"></button>
對於在 HTML 元素上監聽的事件,當 ViewModel 銷燬時,全部的事件處理器會自動刪除,無需本身清理。

3.2 修飾符

Vue 能夠將原生事件對象參數 event 傳入事件方法中,並提供了特殊變量$event用來訪問元素 DOM 事件。此外能夠經過一些事件修飾符來實現特定的事件,如 .stop.prevent.capture.once 等,經常使用的使用示例:

<!-- 中止單擊事件冒泡,調用 event.stopPropagation()-->
<button @click.stop="doThis"></button>

<!-- 阻止默認行爲,調用 event.preventDefault() -->
<button @submit.prevent="doThis"></button>

<!-- 添加事件偵聽器時使用 capture 事件捕獲模式 -->
<button @click.capture="doThis"></button>

<!-- 點擊回調只會觸發一次 -->
<button @click.once="doThis"></button>

<!-- 只當點擊鼠標左鍵時觸發(2.2.0)  -->
<button @click.left="doThis"></button>

<!-- 串聯修飾符 -->
<button @click.stop.prevent="doThis"></button>

此外,v-on 還提供按鍵修飾符來監聽鍵盤事件,鍵值爲 .keyCode,經常使用有.entry.delete.tab.esc.space.down等,以下:

<!-- 只有在 `keyCode` 是 5 時調用 `vm.submit()` -->
<input v-on:keyup.5="submit">

<!-- 爲重要的 keyCode 如 enter 提供別名-->
<input v-on:keyup.enter="submit">

<!-- 縮寫語法 -->
<input @keyup.enter="submit">
此外還有 系統修飾符監聽鍵盤事件,不一樣的系統其鍵盤/系統修飾符不同。這些按鍵修飾符能夠任意組合使用。

4、v-if、v-show 條件渲染

條件渲染 v-if 根據表達式的值的真假條件渲染元素,在表達式爲真時渲染,爲假時移除。

<p v-if="status === 1">當 status 爲 1 時顯示此行</p>

<p v-else-if="status === 1">當 status 爲 2 時顯示此行</p>

<p v-else>其它狀況默認顯示此行</p>

v-show 也是條件渲染,但只切換元素的 CSS 屬性 display,不管條件真假都會被編譯,相比於 v-if 更適用於頻繁切換場景。

<p v-show="status === 1">當 status 爲 1 時顯示此行</p>

當 data: {status: 2} 時隱藏,但依舊會被編譯,渲染結果爲:
<p style="display: none;">當 status 爲 1 時顯示此行</p>

顯然在 Vue.js 內置的 <template> 元素上可使用 v-if,但不能使用 v-show,能夠思考下爲何。

5、v-for 列表渲染

列表渲染指令 v-for 經常使用於數組遍歷或枚舉一個對象的循環顯示,必須結合 in 使用特定語法 alias in expression 爲當前遍歷的元素提供別名:

<!-- 遍歷一個數組 -->
<div v-for="item in items">{{ item.text }}</div>

<!-- 提供第二個的參數爲數組的索引 -->
<div v-for="(item, index) in items">{{ index }} - {{ item.text }}</div>

<!-- 遍歷對象屬性 -->
<div v-for="value in object">{{ value }}</div>

<!-- 提供第二個可選的參數:對象的鍵名 -->
<div v-for="(value, key) in object">{{ key }}: {{ value }}</div>

<!-- 提供第三個的可選參數:對象的索引 -->
<div v-for="(value, key, index) in object">{{ index }}. {{ key }}: {{ value }}</div>
能夠用 of 替代 in 做爲分隔符

v-forv-if 在同一節點一塊兒使用時,v-for 的優先級比 v-if 更高。

6、v-model 表單控件雙向綁定

v-model 其實也是一個特殊的語法糖,其實實現的數據雙向綁定也可用v-bindv-on實現,但v-model在不一樣表單上會有更加智能的處理。

6.1 文本框

經典的使用案例是對<input><textarea>文本框的雙向數據綁定:

<!-- 輸入框 -->
<input type="text" v-model="message" placeholder="edit me">
<!-- 文本域 -->
<textarea v-model="message" placeholder="edit me"></textarea>
<!-- 實時更新 -->
<p>Message is: {{ message }}</p>

6.2 動態選擇

對於單選按鈕,複選框及選擇框的選項,v-model配合 Vue 實例的數據做爲value屬性值實現不一樣效果,即會忽略全部表單元素的 value、checked、selected 特性的值。

<!--單選按鈕的互斥效果-->
<div id="example-radio">
  <input type="radio" id="one" value="One" v-model="picked">
  <label for="one">One</label>
  
  <input type="radio" id="two" value="Two" v-model="picked">
  <label for="two">Two</label>
  
  <!-- picked 顯示的是 value 的值 -->
  <p>Picked: {{ picked }}</p>
</div>

<!--多選按鈕-->
<div id='example-checkbox'>
  <input type="checkbox" id="one" value="One" v-model="checkedNames">
  <label for="jack">Jack</label>
  <input type="checkbox" id="two" value="Two" v-model="checkedNames">
  <label for="john">John</label>

    <!-- Checked 顯示的是 value 組成的數組 -->
  <p>Checked: {{ checkedNames }}</p>
</div>

6.3修飾符

v-model的修飾符的使用限制在<input>、<select>、<textarea> 和組件。

  • .lazy - 取代 input 監聽 change 事件
  • .number - 輸入字符串轉爲數字
  • .trim - 輸入首尾空格過濾

7、v-pre、v-cloak、v-once

這三個指令的共同點是無需表達式,用法以下:

<!-- 不顯示未編譯的標籤直到實例初始化完 -->
<div v-cloak>{{ message }}</div>
<!-- 須要配合 CSS 隱藏樣式 [v-cloak]{ display: none;}-->

<!-- 只渲染一次,隨後的渲染將被視爲靜態內容並跳過 -->
<div v-once>{{ message }}</div>

<!-- 不會被編譯,直接顯示顯示原始{{ }}標籤 -->
<div v-pre>{{ message }}</div>

繼續加油鴨~ 少年!

相關文章
相關標籤/搜索