Vue 自定义指令的学习与使用

146 阅读4分钟

1. Brief Introduce

// Vue中除了核心功能默认内置的指令 v-model 和 v-show 以外,  它也允许我们注册自定义指令。
// 原因:  
// 虽然在Vue 2.0 里, 代码复用和抽象的主要形式是组件 , 但是有些情况下,我们依然需要获取到DOM元素,
// 然后对其进行底层操作,因此这时候就需要用到自定义指令。

2. vue中自定义指令可以用到的钩子函数:

  • bind :   只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
  • inserted :  被绑定元素插入父节点时调用(仅保证父节点存在,但不一定已被插入文档中)
  • updated :   所在组件的VNode更新时调用,但是可能发生在其子VNode更新之前。指令的值可能发生了改变,也可能没有。
  • componentUpdated :   指令所在组件的VNode及其子VNode全部更新后调用
  • unbind :   只调用一次,指令与元素解绑时调用。

3. 上述五个钩子函数里面的参数

指令钩子函数会被传入以下参数

  • el : 指令所绑定的元素,可以用来直接操作DOM。
  • binding : 一个对象,包含以下property:
  1. name : 指令名,不包括v-前缀。
  2. value : 指令的绑定值 例如: v-my-directive="1 + 1" 中 绑定值为 2
  3. oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
  4. expression:字符串形式的指令表达式。例如 v-my-directive="1 + 1" 中,表达式为 "1 + 1"
  5. arg:传给指令的参数,可选。例如 v-my-directive:foo 中,参数为 "foo"
  6. modifiers:一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true, bar: true }
  • vnode : Vue变异生成的虚拟节点。
  • oldVnode : 上一个虚拟节点,仅在 updatecomponentUpdated 钩子中可用。 注意: 除了 el 之外,其他参数都应该是只读的,,切勿进行修改。如果需要在钩子之间共享数据,建议通过元素的 dataset 来进行。

4.官方使用模板

image.png

// 官方案例: 
//    实现在页面加载后 这个输入框元素获得焦点 
//    虽然可以添加上 autofocus属性 自动聚焦 但是这个功能在 Safari上不工作
//    使用自定义指令实现功能

// 注册一个全局自定义指令 v-focus 
Vue.directive('focus',{
   // 当被绑定的元素插入到DOM中时 
   inserted: function (el) {
      // 聚焦元素
      el.focus()
   }
})

// 如果想注册局部指令 组件中也接受一个 directives 的选项
directives: {
   focus: {
      // 指令的定义
      inserted: function (el) {
         el.focus()
      }
   }
}

// 注册完毕后  可以在模板中的任何元素上使用洗的 v-focus property 如下所示: 
<input v-foucs>

5.个人使用

// 在网页的导航栏上  用户的头像  对img标签的scr属性里面的路径进行自定义指令判定 
// 判断图片是否错误 成功或者错误给与不同的 src取值
// 步骤如下:
//  设置一个自定义指令
//  需要判断用户图片是否错误
//  v-errorImg="defaultImg"
// avatar 是 请求获取的图片  defaultImg 是自己引入的图片
//  <img v-errorImg="defaultImg" :src="avatar" class="user-avatar"> 

<div class="avatar-wrapper">
    <img v-errorImg="defaultImg" :src="avatar" class="user-avatar">
    <span style="margin: 0 3px">{{ name }}</span>
    <i class="el-icon-caret-bottom" />
</div>

image.png

// 注意: 
// 对于上面图的 defaultImg 这个变量,由于 上方img标签里的 scr属性 是取变量值 :scr="avatar"
// 如果avatar 是一个固定的值 那么src 必须去掉':' 绑定  src="图片路径"
// defaultImg的值 由于是在模块化组件里面  因此引入过来也需要模块化的方式导入
// 方法一: 
import defaultImg from '../../assets/common/rabbit.gif'
export default {
   data() {
      return {
       defaultImg: defaultImg
      }
   }
}


// 方法二:  直接data里面使用require导入  
data() {
   return {
     defaultImg: require("../../assets/common/head.jpg")
   }
}
// 在main.js里面注册全局 自定义指令 如果图片出错时执行这个指令
Vue.directive('errorImg',{
   inserted(el,binding) {
       console.log(el,888)  // 打印出来的el 的结果是自定义指令绑定的这个dom元素
       console.log(binding,999) // 打印出来的是一个对象
     
       el.onerror = function() {
          // 元素加载执行的时候出现错误就会触发这个事件 事件触发 表示资源加载失败
          console.log('图片加载失败')
          // 解决办法:  如果图片加载失败 就显示默认图片  加载成功就不用管
          el.src = binding.value
       }
   } 
})
// main.js里面的 自定义指令的el 结果如下图所示  就是当前绑定的这个DOM元素 

image.png

// main.js里面的 自定义指令的binding 结果如下图所示  
// 打印出来的是一个对象 里面的value就是自定义指令绑定的值 也就是 defaultImg的值
// 如果右边 src 里面的 avatar(发送请求获取的图片) 出错 就会触发 el.error 函数
// 然后将src设置成默认的图片 defaultImg  否则显示avatar(请求获取到的图片)

snipaste20220414_190521.jpg

image.png

5.1 注意:

//   avatar里面的数可能为空null  导致某种情况下 img 直接没有src属性出来 
//   这时候使用v-errorImg 自定义指令就无法生效 因为没办法进入指令
//   解决办法: 取出自定义指令 src进行三元表达式判断 图片是否对错 对就取这个值 否则取其他 

<img :src="avatar ? avatar : defaultImg " class="user-avatar">

// 具体情况如下:  img标签里面没有src属性

image.png