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:
name: 指令名,不包括v-前缀。value: 指令的绑定值 例如:v-my-directive="1 + 1"中 绑定值为2。oldValue:指令绑定的前一个值,仅在update和componentUpdated钩子中可用。无论值是否改变都可用。expression:字符串形式的指令表达式。例如v-my-directive="1 + 1"中,表达式为"1 + 1"。arg:传给指令的参数,可选。例如v-my-directive:foo中,参数为"foo"。modifiers:一个包含修饰符的对象。例如:v-my-directive.foo.bar中,修饰符对象为{ foo: true, bar: true }。
vnode: Vue变异生成的虚拟节点。oldVnode: 上一个虚拟节点,仅在update和componentUpdated钩子中可用。 注意: 除了el之外,其他参数都应该是只读的,,切勿进行修改。如果需要在钩子之间共享数据,建议通过元素的dataset来进行。
4.官方使用模板
// 官方案例:
// 实现在页面加载后 这个输入框元素获得焦点
// 虽然可以添加上 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>
// 注意:
// 对于上面图的 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元素
// main.js里面的 自定义指令的binding 结果如下图所示
// 打印出来的是一个对象 里面的value就是自定义指令绑定的值 也就是 defaultImg的值
// 如果右边 src 里面的 avatar(发送请求获取的图片) 出错 就会触发 el.error 函数
// 然后将src设置成默认的图片 defaultImg 否则显示avatar(请求获取到的图片)
5.1 注意:
// avatar里面的数可能为空null 导致某种情况下 img 直接没有src属性出来
// 这时候使用v-errorImg 自定义指令就无法生效 因为没办法进入指令
// 解决办法: 取出自定义指令 src进行三元表达式判断 图片是否对错 对就取这个值 否则取其他
<img :src="avatar ? avatar : defaultImg " class="user-avatar">
// 具体情况如下: img标签里面没有src属性