Vue自定义防抖指令,并将其应用于项目

前言

  • 条件渲染指令( 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';
        }
    })
}

其中有两个参数:elbinding,分别代表是

  1. el: 表示被绑定的元素,即指令所在的 DOM 元素。这是一个原生 DOM 元素对象。

  2. 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函数。这样我们的防抖函数就写好啦,看看实际效果:

可以看到,当我们一直点击的时候,只有我们不点击后的最后一次点击才会执行事件,这样我们带参的防抖指令也是成功完成啦!

总结

实际的防抖指令业务逻辑可能更为复杂,如果各位掘友觉得本文有不对的地方,欢迎评论指出喔😘😘😘。要是觉得文章对您有所帮助的话,可以留下一个美美的赞鼓励一下嘛🌹🌹🌹,码字不易,后续还会更新一些其他项目功能的代码文章,欢迎各位掘友支持!😭😭😭

相关推荐
Myli_ing10 分钟前
HTML的自动定义倒计时,这个配色存一下
前端·javascript·html
dr李四维27 分钟前
iOS构建版本以及Hbuilder打iOS的ipa包全流程
前端·笔记·ios·产品运营·产品经理·xcode
I_Am_Me_41 分钟前
【JavaEE进阶】 JavaScript
开发语言·javascript·ecmascript
雯0609~1 小时前
网页F12:缓存的使用(设值、取值、删除)
前端·缓存
℘团子এ1 小时前
vue3中如何上传文件到腾讯云的桶(cosbrowser)
前端·javascript·腾讯云
学习前端的小z1 小时前
【前端】深入理解 JavaScript 逻辑运算符的优先级与短路求值机制
开发语言·前端·javascript
星星会笑滴1 小时前
vue+node+Express+xlsx+emements-plus实现导入excel,并且将数据保存到数据库
vue.js·excel·express
前端百草阁1 小时前
【TS简单上手,快速入门教程】————适合零基础
javascript·typescript
彭世瑜1 小时前
ts: TypeScript跳过检查/忽略类型检查
前端·javascript·typescript
FØund4041 小时前
antd form.setFieldsValue问题总结
前端·react.js·typescript·html