Vue自定义指令及实现图片懒加载指令
一. 速识概念:
在我们使用 Vue 的过程中,遇到了很多方便我们操作的vue内置指令,以 v-xxx 表示。比如有 v-module,v-for,v-if,v-show 等等,每个指令都能实现一些相对应的功能。但是,在实际的开发过程中,可能这些内置指令并不能满足所有的需求,这时候,就需要用到 Vue 给我们提供的一个强大又灵活的功能「 自定义指令 」。
同样,vue自定义指令可以分为全局注册指令和局部注册指令。下面我将以最简单的例子带你认识vue自定义指令。
二.全局注册指令:
比如,我们想要定义一个 v-color=" " 指令 ,标签引用这个指令后可以改变自身背景颜色。一个全局注册指令的基本语法如下:
Vue.directive('color',{
bind(){},
inserted(){},
update(){},
componentUpdated(){},
unbind()
})
第一个参数,color 为自定义指令的名称,不用带 v- 。第二个参数为一个对象,其中有5个钩子函数,你可以类似于vue的生命周期钩子函数,它们也是被绑定元素各个周期会触发的钩子函数。每个的执行期间如下:
bind():只调用一次,指令第一次绑定到HTML元素时调用。在这里可以进行一次性的初始化设置。
inserted():当指令绑定的元素插入到父节点中的时候触发。
update():当指令绑定的元素状态/样式、内容(这里指元素绑定的 vue 数据) 发生改变时触发。
componentUpdated():当 update() 执行完毕之后触发。
unbind():只调用一次,指令与元素解绑时调用。
其实,我们最常用的就是 bind()和 inserted(),也可以理解为在 bind()里设置被绑定元素的css样式,在 inserted()里设置被绑定元素的 js 操作。
我们的 v-color=" " 指令 ,标签引用这个指令后可以改变自身背景颜色,只定义bind()函数就行,如下:
<div v-color="'red'">北极光之夜。</div>
-------------------------------------------
Vue.directive("color", {
bind(el, binding) {
console.log(el);
console.log(binding);
},
});
其中,每个钩子函数都有4个参数,我们只讨论 el 和 binding ,打印看看是什么:
可以看到,el 就是使用该指令的元素,而binding为一个对象,它保存着很多值,根据vue官方文档,其属性值包括:
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 }。
那么就很简单了,我们想利用 v-color 自定义指令把背景颜色改为红色可以如下设置:
<div v-color="'red'">北极光之夜。</div>
-------------------------------------------
Vue.directive("color", {
bind(el, binding) {
el.style.cssText = `background-color:${binding.value}`;
},
});
效果成功:
函数简写形式:
在很多时候,你可能想在 bind 和 update 时触发相同行为,而不关心其它的钩子。这时候函数可以简写如下:
Vue.directive("color", function (el, binding) {
el.style.cssText = `background-color:${binding.value}`;
});
三.局部注册指令:
上面我们定义的全局自定义指令是在Vue实例上定义的,全局可以,如果我只想在某个组件上使用也是可以的,vue组件中规定了directives方法,与data和methods这些同级别,如下:
<div id="app">
<div v-color="'red'">北极光之夜。</div>
</div>
--------------------------------------
var app = new Vue({
el: "#app",
data: {},
directives: {
color: {
bind(el, binding) {
el.style.cssText = `background-color:${binding.value}`;
},
},
},
});
可以看到跟全局也是差不多写法,就是换个位置写而已。
四:图片懒加载:
我们可以用自定义指令实现图片懒加载。这里只介绍写法,关于图片懒加载原理可以看我另一篇文章,对懒加载原理和原生js实现分析的很全面:前端必会的图片懒加载,你造吗? 。地址 https://auroras.blog.csdn.net/article/details/119789741 看完了再回来看这里就一目了然啦~
下面将用到 Intersection Observer 观察器接口实现懒加载。
1.建一个HTML单页面,引入vue,然后new一个vue实例,变量moren为图片默认地址,arrSrc数组为图片真实地址:
var app = new Vue({
el: "#app",
data: {
moren: "img/0.png",
arrSrc: [
"img/1.jpg",
"img/2.jpg",
"img/3.jpg",
"img/4.jpg",
"img/5.jpg",
"img/6.jpg",
"img/7.jpg",
"img/8.jpg",
],
},
});
2.使用 v-for 渲染 arrSrc 数组,但是图片的src都设为moren:
<div id="app">
<div class="container">
<img
v-for="(item,index) in arrSrc"
:key="index"
:src="moren"
alt="x"
/>
</div>
</div>
此时页面效果如下:
3.定义 v-lazy = “图片地址” 自定义指令:
<img
v-for="(item,index) in arrSrc"
:key="index"
:src="moren"
v-lazy="item"
alt="x"
/>
实现:
Vue.directive("lazy", {
inserted(el, binding) {
//定义一个观察器,entries为状态改变元素的数组
let observer = new IntersectionObserver((entries) => {
// 遍历
for (let i of entries) {
// 如果改元素处于可视区
if (i.isIntersecting > 0) {
// 获取该元素
let img = i.target;
// 重新设置src值
img.src = binding.value;
//取消对该元素的观察
observer.unobserve(img);
}
}
});
// 为 img 标签添加一个观察
observer.observe(el);
},
});
效果,可以看到右边控制台,当图片出现在可视区时才加载:
五.总结:
上面就是vue自定义指令的一些简单用法与应用的全部内容啦。总的来说,Vue 给我们提供的一个强大又灵活的功能「 自定义指令 ,可以分为全局注册指令和局部注册指令。全局注册为 Vue.directive(‘name’,{ bind(el,binding){} ,inserted(el,binding){}})。其中,el为该元素,binding为一个对象等等。当然,vue自定义指令肯定没这么简单,在一些复杂用法上是很难的,只能说学无止境了~
下次见啦~
- 点赞
- 收藏
- 关注作者
评论(0)