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

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

总结

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

相关推荐
zhougl99632 分钟前
html处理Base文件流
linux·前端·html
花花鱼36 分钟前
node-modules-inspector 可视化node_modules
前端·javascript·vue.js
HBR666_39 分钟前
marked库(高效将 Markdown 转换为 HTML 的利器)
前端·markdown
careybobo2 小时前
海康摄像头通过Web插件进行预览播放和控制
前端
TDengine (老段)3 小时前
TDengine 中的关联查询
大数据·javascript·网络·物联网·时序数据库·tdengine·iotdb
杉之4 小时前
常见前端GET请求以及对应的Spring后端接收接口写法
java·前端·后端·spring·vue
喝拿铁写前端4 小时前
字段聚类,到底有什么用?——从系统混乱到结构认知的第一步
前端
再学一点就睡4 小时前
大文件上传之切片上传以及开发全流程之前端篇
前端·javascript
木木黄木木5 小时前
html5炫酷图片悬停效果实现详解
前端·html·html5
请来次降维打击!!!5 小时前
优选算法系列(5.位运算)
java·前端·c++·算法