什么是自定义指令?
除了使用 Vue 提供的内置指令之外,我们可以自定义一些自己的指令
什么时候需要自定义指令?
当需要不可避免的操作 DOM 的时候,使用自定义指令来解决
如何注册和使用自定义指令?
一、注册
1 . 全局注册,在任何组件中都可以使用全局注册自定义指令
2 . 局部注册,只能在当前组件使用该指令
3 . 如果需要在多个不同的组件中使用该指令,则把它定义为全局的
4 . 非通用的,不需要多次使用的指令我们定义到局部—— 到底是否通用取决于你的功能业务
二、 使用
eg:注册一个全局自定义指令 v-focus
Vue.directive(‘指令名称’, {选项参数})
-
第一个参数:即指令名字
- 指令的名字随便起,但是在使用的时候务必加上 v- 前缀,所以我们在其名字的时候就不要加 v- 前缀
- 如果是驼峰命名法的名称,则在使用的时候需要把驼峰转为小写使用 - 连接起来
-
第二个参数就是需要配置指令的生命钩子函数
-
每个钩子函数都可以接收两个参数:
el
作用该指令的 DOM 对象
binding
一个对象,可以获取指令的值等信息。。。
-
指令是可以传值的。什么意思呢?例如 v-show=“布尔值”
Vue.directive('focus', {
// 当被绑定的元素插入到 DOM 中时……
// el 参数就是你作用该指令的 DOM 元素
// 只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
// bind 中拿不到父元素
bind (el) {
console.log('bind', el.parentNode)
},
// 被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
// 如果你需要操作作用指令的父元素,则最起码写到这个 inserted 中
inserted (el) {
console.log('inserted', el.parentNode)
},
update () {
console.log('update')
},
componentUpdated () {
console.log('componentUpdated')
},
unbind () {
console.log('unbind')
}
})
模拟 v-show 实现,根据值的真假来显示或者隐藏作用该指令的元素
Vue.directive('my-show', {
// bind 和 inserted 的相同之处是一上来都执行一次,以后再也不会执行
// 异同之处在于,bind 拿不到父元素,inserted 可以拿到父元素
bind (el, binding) {
// console.log('my-show bind', el, binding)
// if (binding.value) {
// el.style.display = 'block'
// } else {
// el.style.display = 'none'
// }
},
inserted (el, binding) {
console.log('my-show inserted')
if (binding.value) {
el.style.display = 'block'
} else {
el.style.display = 'none'
}
},
// 紧接着我们发现 update 和 componentUpdated 只有在指令的绑定的值发生更新的时候才会触发
update (el, binding) {
// console.log('my-show update', el, binding)
console.log('my-show update', el.innerHTML)
if (binding.value) {
el.style.display = 'block'
} else {
el.style.display = 'none'
}
},
componentUpdated (el, binding) {
console.log('my-show componentUpdated', el.innerHTML)
},
unbind () {
console.log('my-show unbind')
}
})
update 和 componentUpdated 的区别是:
- update 中获取的是更新的之前的指令所在的 DOM 内容
- componentUpdated 获取的是更新之后的最新 DOM 内容
- 也就是说如果你需要获取数据改变视图之前的内容,则把代码写到 update 中如果需要获取数据改变视图之后的内容,则把代码写到 componentUpdated 里面
钩子函数:
-
bind函数:每当指令绑定到元素上的时候,会立即执行这个 bind 函数,只执行一次
- 拿不到父元素
- 和样式相关的操作,一般都可以在 bind 执行
-
inserted:表示元素 插入到DOM中的时候,会执行 inserted 函数【触发1次】
- 和js 行为有关的最好写入Inserted去执行,js放置不生效
-
update:当VNode更新的时候,会执行 updated, 可能会触发多次
-
关于函数简写,直接绑定到bind 与 update
// 自定义全局指令 v-focus,为绑定的元素自动获取焦点:
Vue.directive('focus', { inserted: function (el) { // inserted 表示被绑定元素插入父节点时调用 el.focus(); } }); // 在元素 刚绑定了指令的时候,还没有 插入到 DOM中去,这时候,调用 focus 方法没有作用 // 因为,一个元素,只有插入DOM之后,才能获取焦点 // el.focus() // 样式只要通过指令绑定给了元素,不管这个元素有没有被插入到页面中去,这个元素肯定有了一个内联的样式 // 将来元素肯定会显示到页面中,这时候,浏览器的渲染引擎必然会解析样式,应用给这个元素 // 自定义局部指令 v-color 和 v-font-weight,为绑定的元素设置指定的字体颜色 和 字体粗细: directives: { color: { // 为元素设置指定的字体颜色 bind(el, binding) { el.style.color = binding.value; //通过形参(bingding)拿值 } }, 'font-weight': function (el, binding2) { // 自定义指令的简写形式,等同于定义了 bind 和 update 两个钩子函数 el.style.fontWeight = binding2.value; } }
- 自定义指令的使用方式:
< input type=“text” v-model=“searchName” v-focus v-color="‘red’" v-font-weight=“900” >