前言
- 条件渲染指令( v-show 、 v-if 、 v-else 、 v-else-if )
- 事件绑定指令( v-on )
- 属性绑定指令 ( v-bind )
- 双向绑定指令( v-model )
- 列表渲染指令( v-for )
相信大家对这些vue中常用的指令已经玩弄于股掌之中了,在我们写项目的时候,这些指令必不可少。但我们在实际项目开发中,有时候光靠这些指令还解决不了问题,就拿角色权限控制来说,同一个页面,有些功能是仅管理员账号可见的,而普通用户看不见,如果是只有一个功能仅管理员可用,我们用个v-if判断一下也不是不可以吼,但要是有N多个功能呢,用v-if是不是就有点鸡肋了,所以这时候就需要我们自己自定义一个指令来解决这个问题。
同样的,在开发项目的时候,对于按钮的提交或者点击,为了避免用户在同一个时间内,多次点击触发事件,我们一般就会用到事件防抖,来限制按钮点击的频率,避免重复提交操作。但是,在项目中,我们可能有多个地方都需要用到防抖,所以为了减少代码量,这时候我们就可以自定义一个防抖指令,实现复用就好了。这篇文章将会带大家实现自定义防抖指令,并将它应用到实际项目中。
如何自定义指令(实现v-show效果)
为了让大家明白什么是自定义指令,以及如何实现自定义指令,我们首先来简单实现一下自定义v-show的效果。 先给段代码:
html
<div>
<div class="box">我是盒子</div>
<button @click="handle">{{ flag ? '盒子消失' : '盒子出现'}}</button>
</div>
效果如下:
现在我们要做的事情就是,通过我们自己定义一个指令,就叫v-domIf
吧,后面那个名字可以自己随便取,来实现和v-show
一样的功能,在我们点击按钮(盒子消失),就可以让盒子消失,再点击(盒子出现)又可以让出现。
好,现在我们来实现一下,为了代码模块化管理,我们在项目中scr目录下新建一个directives(指令)文件夹,在里面新建一个domIf.js
文件,在里面写上我们的指令代码:
js
export default (app)=>{
//定义domIf指令
app.directive('domIf',(el,binding)=>{
if(binding.value) //使用指令时绑定的值
el.style.display = '';
else{
el.style.display = 'none';
}
})
}
其中有两个参数:el
和binding
,分别代表是
-
el
: 表示被绑定的元素,即指令所在的 DOM 元素。这是一个原生 DOM 元素对象。 -
binding
: 是一个包含指令信息的对象。binding.value
: 指令绑定的值,即在指令表达式中的值。
如果这个还不是很明白,我们继续往下看,到后面我们就恍然大悟了。接下来我们在main.js中引入这份代码,将该指令进行全局注册。
main.js
import { createApp } from 'vue'
import App from './App.vue'
import domIf from './directives/domIf' //引入指令文件
const app = createApp(App)
app.use(domIf) //进行全局注册
app.mount('#app')
好,完成了这些工作,我们现在就自定义好了一个v-domIf
指令啦!现在我们来使用一下,我们在盒子box上使用该指令,代码如下:
html
<div>
<div class="box" v-domIf="flag">我是盒子</div>
<button @click="handle">{{ flag ? '盒子消失':'盒子出现' }}</button>
</div>
js
<script setup>
import { ref } from 'vue'
const flag = ref(false)
const handle = ()=>{
flag.value = !flag.value
}
</script>
测试一下效果:
可以看到,功能成功实现啦~小伙伴们看到这里是不是悟了😍,好,知道了如何自定义指令,我们现在趁热打铁,再来实现一下自定义防抖指令。
自定义防抖指令
(注:接下来我写的防抖代码和我之前文章的防抖代码是一致的,如果有小伙伴对防抖还不是很清楚的话,可以先看看我之前的文章嗷~~🌹,非常详细地介绍了如何实现防抖代码,本篇文章就不再说明了喔)
同样的,我们在directives(指令)文件夹下新建一个文件Debounce.js,然后写上我们防抖的代码:
js
export default (app)=>{
//定义debounce指令
app.directive('debounce',{
mounted(el,binding){
el.debounceFn = debounce(binding.value, 500)
el.addEventListener('click',el.debounceFn)
}}
)}
//实现防抖函数代码
//(我之前文章有详解)
function debounce(fn,delay){
let name;
return function(){
let _this = this;//这个this指向btn
let arr = arguments //包含传递给函数的每个参数
if(name) clearTimeout(name) //name有值,说明上次定时器还没执行完,这时清除上次定时器
name = setTimeout(function(){
fn.call(_this,...arr) //将fn函数的this指向_this(btn)
//arguments里的每个参数展开到send函数中作为实参
}, delay);
}
}
然后在main.js中再进行全局注册,代码如下:
js
import { createApp } from 'vue'
import App from './App.vue'
import domIf from './directives/domIf'
import Debounce from './directives/Debounce'
const app = createApp(App)
app.use(domIf)
app.use(Debounce)
app.mount('#app')
我们拿开始的例子代码来测试一下这个指令效果,我们将代码修改为:
html
<div>
<div class="box" v-domIf="flag">我是盒子</div>
<button v-debounce="handle">{{ flag ? '盒子消失':'盒子出现' }}</button>
</div>
js
<script setup>
import { ref } from 'vue'
const flag = ref(false)
const handle = ()=>{
flag.value = !flag.value
console.log('我被点鸡啦');
}
</script>
看看效果如何:
非常nice!,可以看到,在我们一波按钮狂点之下,只有最后一次点击事件响应了,说明我们的防抖指令成功实现啦!好,防抖指令成功实现啦~我们将它应用至项目之中。
将防抖指令应用到项目
防抖指令我们已经写好了,现在是不是哪里需要就往哪里搬就好咯!CV我最擅长了,嘿嘿嘿!
以下是没有加防抖的效果,点击购买数量会有一个小球出来的动画,为了避免多次点击出现bug,所以我在这里加了一个防抖的代码:
自定义防抖代码如下:
js
export default (app)=>{
//定义debounce指令
app.directive('debounce',{
mounted(el, binding){
// 获取传递给指令的参数
const debounceConfig = {
fn: binding.value.handler,
args: binding.value.args || [], // 如果args没有传递,默认为空数组
};
el.debounceFn = debounce(debounceConfig, 200)
el.addEventListener('click',el.debounceFn)
}}
)}
//实现防抖函数代码
//(我之前文章有详解)
//fn相当于要执行防抖的函数,args是该函数的参数
function debounce({fn,args},delay){
let name;
return function(){
let _this = this;//这个this指向btn
let arr = arguments //包含传递给函数的每个参数
if(name) clearTimeout(name) //name有值,说明上次定时器还没执行完,这时清除上次定时器
name = setTimeout(function(){
fn.call(_this,...arr,...args) //将fn函数的this指向_this
//arguments里的每个参数展开到send函数中作为实参
// 调用防抖的处理函数,并传递参数
}, delay);
}
}
html
<el-input v-debounce="{ handler:changeAnimation, args:[$index]}"/>
在这里因为防抖事件changeAnimation
需要传递参数$index
,而防抖的事件函数不能直接传递参数,所以这里的代码需要这样写,得通过防抖的处理函数接收到参数,然后再将参数传递回我们的changeAnimation
函数。这样我们的防抖函数就写好啦,看看实际效果:
可以看到,当我们一直点击的时候,只有我们不点击后的最后一次点击才会执行事件,这样我们带参的防抖指令也是成功完成啦!
总结
实际的防抖指令业务逻辑可能更为复杂,如果各位掘友觉得本文有不对的地方,欢迎评论指出喔😘😘😘。要是觉得文章对您有所帮助的话,可以留下一个美美的赞鼓励一下嘛🌹🌹🌹,码字不易,后续还会更新一些其他项目功能的代码文章,欢迎各位掘友支持!😭😭😭