Vue.directive() 封装DOM操作
这篇文章是关于Vue Directive的介绍,后面会介绍一个使用的小例子。
1.Vue Directive的简介
directive在Vue中十分常见,Vue提供的许多指令如 v-on 、 v-show 使得Vue的功能更加强大,可是仍然有一些操作指令是Vue没有提供的,不过Vue提供了自定义directive的属性方法来满足这一需求。其实,Vue Directive就是一种特殊的HTML元素属性。
Vue提供了两中注册方法,一种是全局注册,在Vue.directive中定义组件的名字和相关指令操作
Vue.directive('指令的名字', {
//一些option,提供许多hook function 定义directive的具体操作,如inserted、bind...
inserted: function (el) {
//指令插入元素后的操作
}
})
另一种是局部注册,在对应组件的directives属性里注册组件名,传入指令的option对象
directives: {
name: { //指令的名字
// 指令的定义
}
}
在定义时,Vue提供了许多hook function,例如 inserted 、bind等,bind是只会在绑定的对象节点被插入父节点时调用一次的函数,与unbind相对应,unbind将也只会在元素被解除绑定时调用。
Vue.directive('指令的名字', {
bind: function(el, binding, vnode,oldVnode) {
//绑定指令时调用
},
unbind: function() {
//指令解除绑定时调用
}
})
bind函数中的binding,是一个包含了众多属性的对象,关于它的所有的性质的介绍可以自行查看官方文档 ,比较常用的一个属性binding.value,与其对应的是在指令中传入的字符串,Vue会自动解析这个值并执行。与此相对应的另一个属性binding.expression里的值则就是原始值。
2.为什么要使用VueDirective
有同学可能会问,我在Vue实例的方法中写DOM操作不可以吗?那为什么使用Vue Directive来封装DOM操作呢?
这是因为,为了实现View和ViewModel的分离,我们必须封装DOM操作,View层负责页面上的显示,ViewModel层负责改变操作数据,由于Vue是数据驱动的,属于ViewModel层,那么其中就不应该出现View层上的DOM操作,而且,使用Vue Directive是和DOM元素的创建、销毁绑定的。Vue Directive的生命周期方法能让我们更优雅的去在合适的时机进行DOM的操作。而在ViewModel里则没有和DOM元素对应的方法。因为Vue Directive是属于View层面的,所以DOM操作应该被封装在Vue Directive里而不是出现在Vue实例中。
3. Demo:自制scroll指令
接下来看一个具体使用Vue Directive封装DOM操作的scroll事件的例子,在这个例子中需求是在用户滑动到页面的底端时请求更多数据。
3.1 首先将DOM操作封装到指令的option中
let scrollCallback = function(callback) {
if (document.body.scrollHeight < 1000) {
return
}
if (document.body.scrollHeight - window.scrollY - 100 document.body.clientHeight) {
callback()
}
}
let callBackWarpped // 新变量 保存引用
export default {
bind: function(el, binding, vnode) {
callBackWarpped = scrollCallback.bind({}, binding.value)
window.addEventListener("scroll", callBackWarpped)
},
unbind: function() {
window.removeEventListener("scroll", callBackWarpped)
}
}
首先需要监听页面的滚动,如果触发了scroll事件那么就要执行回调函数,由于在解除绑定的时候也要将监听事件从window上移除,所以必须给回调函数取一个名字,例如本例中的scrollCallback,并在unbind函数中将监听移除,因此scrollCallBack的具体定义应在对象外执行。
并且回调函数应该在页面滑动到底端时才执行,也就是说不能马上执行 binding.value,怎样实现这一点呢?可以将bind.value作为函数的参数传进scrollCallback,先判断,然后在满足条件时调用binding.value 。
3.2 在组件里import一个directive
import scrollDirective from '../../directives/scroll'
//import 指令的option的名字 from '指令option的位置'
使用import将directive引入组件。
3.3 在组件的directives属性中注册这个指令,值为scroll
directives: {
scroll: scrollDirective
//指令的名字:指令的option的名字
}
将引入的组件注册到scroll上。
3.4 在相应元素上加上directive指令
v-scroll = "onScroll"
//v-'指令的名字' = "回调函数"
用注册好的名字在相对应的元素上加入指令 。
3.5 编写directive指令中的函数
最后在method中编写onScroll函数,也就是上文中对应的binding.value,在这个函数中我们将会请求更多数据,而Vue就会执行相应v-scroll中的值。
具体的Demo请戳这里