vue自定義指令實現v-model


概要

指令是vue中非常重要的內容,了解指令的用法可以更好的服務於業務場景,方便高效,本文主要介紹指令的基本概念和用法,簡單模擬v-model實現的功能。

自定義指令

除了內置指令,Vue.js 也允許注冊自定義指令。自定義指令提供一種機制將數據的變化映射為 DOM 行為。
可以用 Vue.directive(id, definition) 方法注冊一個全局自定義指令,它接收兩個參數,指令 ID 與定義對象。也可以用組件的 directives 選項注冊一個局部自定義指令。

鈎子函數

定義對象可以提供幾個鈎子函數(都是可選的):

  • bind:只調用一次,在指令第一次綁定到元素上時調用。

  • update: 在 bind 之后立即以初始值為參數第一次調用,之后每當綁定值變化時調用,參數為新值與舊值。

  • unbind:只調用一次,在指令從元素上解綁時調用。

例如

Vue.directive('my-directive', {
  bind: function () {
    // 准備工作
    // 例如,添加事件處理器或只需要運行一次的高耗任務
  },
  update: function (newValue, oldValue) {
    // 值更新時的工作
    // 也會以初始值為參數調用一次
  },
  unbind: function () {
    // 清理工作
    // 例如,刪除 bind() 添加的事件監聽器
  }
})

在注冊之后,便可以在 Vue.js 模板中這樣用(記着添加前綴 v-):

<div v-my-directive="someValue"></div>

當只需要 update 函數時,可以傳入一個函數替代定義對象:

Vue.directive('my-directive', function (value) {
  // 這個函數用作 update()
})

指令實例屬性

所有的鈎子函數將被復制到實際的指令對象中,鈎子內 this 指向這個指令對象。這個對象暴露了一些有用的屬性:

  • el: 指令綁定的元素。
  • vm: 擁有該指令的上下文 ViewModel。
  • expression: 指令的表達式,不包括參數和過濾器。
  • arg: 指令的參數。
  • name: 指令的名字,不包含前綴。
  • modifiers: 一個對象,包含指令的修飾符。
  • descriptor: 一個對象,包含指令的解析結果。

示例:

<div id="demo" v-demo:hello.a.b="msg"></div>
Vue.directive('demo', {
  bind: function () {
    console.log('demo bound!')
  },
  update: function (value) {
    this.el.innerHTML =
      'name - '       + this.name + '<br>' +
      'expression - ' + this.expression + '<br>' +
      'argument - '   + this.arg + '<br>' +
      'modifiers - '  + JSON.stringify(this.modifiers) + '<br>' +
      'value - '      + value
  }
})
var demo = new Vue({
  el: '#demo',
  data: {
    msg: 'hello!'
  }
})

結果:

name - demo
expression - msg
argument - hello
modifiers - {"b":true,"a":true}
value - hello!

用自定義指令實現v-model類似的功能

import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

Vue.directive('input', {
  bind: function (el, binding, vnode) {
    const { value, expression } = binding
    const { context } = vnode
    el.value = value

    el.oninput = (e) => {
      const value = e.target.value
      context[expression] = value
    }
  },
  update: function () {}
})

new Vue({
  render: h => h(App),
}).$mount('#app')

測試:

<template>
  <div id="app">
    <input type="text" v-input="value1">
    <br>
    value:{{ value1 }}
  </div>
</template>

<script>

export default {
  name: 'App',
  data () {
    return {
      value1: 'test'
    }
  }
}
</script>

以上實現了數據的雙向綁定,當然我們可以使用參數和修飾符實現更加復雜的功能,有興趣的同學可以學習一下。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM