这是我参与8月更文挑战的第9天,活动详情查看:8月更文挑战
自定义指令
- 有些情况下,你可能需要对普通 DOM 元素进行底层操作,这时候就会用到自定义指令。也就是说,
自定义指令是操作底层DOM元素的。
比方说:打开页面的时候自动聚焦到某个input框,通常的做法是 定义ref,并在mounted中调用该input框的focus方法。当然,我们也可以用自定义指令:
// 注册一个全局自定义指令 `v-focus`
Vue.directive('focus', {
// 当被绑定的元素插入到 DOM 中时……
inserted: function (el) {
// 聚焦元素 el.focus()
}
})
// 定义一个局部的指令,可以在组件内部的directives选项下定义
directives: {
focus: {
// 指令的定义
inserted: function (el) {
el.focus()
}
}
}
// 使用
<input v-focus>
自定义指令的钩子函数
bind:只调用一次,指令第一次 绑定 到元素时调用。在这里可以进行一次性的初始化设置。inserted:被绑定元素插入父节点时调用(仅保证父节点存在,但不一定已被插入文档中)。update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。unbind:只调用一次,指令与元素解绑时调用。
指令钩子函数会被传入的参数
el:指令所绑定的元素,可以用来直接操作 DOM。binding:是一个对象,包含以下属性: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之外,其它参数都应该是只读的,切勿进行修改。
动态的指令参数
- 指令的参数可以是动态的。例如,在
v-mydirective:[argument]="value"中,argument参数可以根据组件实例数据进行更新!
实现一个vue的列表滚动加载 自定义指令
都知道,在开发过程中会涉及到很多的列表页面,而大部分列表页是需要分页加载的,那么这时候我们在PC段通常是采用paganation组件,进行分页处理。在移动端则更多的是采用滚动加载。下面我们就来实现以下滚动加载吧。
- 在单文件组件的directives选项下,创建loadMore指令;
// 注意:但文件组件的vue格式有很多种写法,此处是其中一种
export default Vue.extend({
directives: {
loadmore: {}
}
})
- 接下来我们将 指令 绑定到 我们需要的元素上;
loadmore: {
// 指令第一次 绑定 到元素时,调用bind钩子,
bind(el, binding) {
},
}
- 在指令第一次绑定到元素上时,我们对需要滚动加载的元素添加滚动事件;
loadmore: {
// 指令第一次 绑定 到元素时,调用bind钩子,
bind(el, binding) {
let dom = el.querySelector('.bg');
dom &&
dom.addEventListener('scroll', function () {
const condition = this.scrollHeight - this.scrollTop <= this.clientHeight;
if (condition) {
// 因为我们指令绑定的是一个加载更多的方法,所以此处调用绑定的方法
binding.value();
}
});
},
unbind(el, binding) {
let dom = el.querySelector('.bg');
dom && dom.removeEventListener('scroll')
},
}
- 我们将定义好的自定义指令绑定到元素上;
<template>
<div class="page" v-loadmore="loadMoreData">
<div class="bg"></div>
</div>
</template>
<script>
export default Vue.extend({
methods: {
// 加载更多的方法
loadMoreData() {
// 拿到此时页面中的数据总数
let datalength = this.pagingResult.pageNo * this.pagingResult.pageSize;
// 接口返回的实际数据总数
let rowTotal = this.pagingResult.total;
// 如果接口的实际总数大于 页面已拿到的数据总数,则去加载更多数据
if (rowTotal > datalength) {
this.pagingResult.pageNo += 1;
// 调用函数 获取数据
this.getList();
}
},
}
})
</script>
- 至此,我们的一个简单的自定义指令已经开发完成了。
写在最后
如果写的有的不对的,或者能够改进的地方,欢迎大佬们评论区指出。感谢🙏🙏🙏