1.VUE常用指令大全

本项目所有指令均为全局注册,使用时直接在组件中使用即可。

指令目录:src/directives

页面目录:src/views

具体可查看源码

1.1 权限指令

封装一个权限指令,在模板中根据用户权限来控制元素的显示或隐藏。

permission.js

import { ref, watchEffect } from 'vue';

const hasPermission = (permission) => {
// 在实际项目中,根据后端返回的用户权限进行判断
const userPermissions = ['view', 'edit'];
return userPermissions.includes(permission);
}; export default {
beforeMount(el, binding) {
const { value } = binding;
const visible = ref(false); // 监听权限变化,当权限发生改变时重新判断是否显示元素
watchEffect(() => {
visible.value = hasPermission(value);
}); // 根据 visible 的值来显示或隐藏元素
el.style.display = visible.value ? 'block' : 'none';
}
}

Permission.vue

<template>
<div>
<button v-permission="'view'">View Button</button>
<button v-permission="'edit'">Edit Button</button>
<button v-permission="'delete'">Delete Button</button>
</div>
</template> <script>
export default {
name: "Permission"
}
</script> <style scoped> </style>

1.2 防抖函数指令

在模板中使用防抖功能,可以用于减少频繁触发的事件的执行次数,比如在输入框中的实时搜索场景

debounce.js

//第一次触发也需要等待
export default {
beforeMount(el, binding) {
const { value } = binding; // 需要回调函数以及监听事件类型
if (typeof value.fn !== 'function' || !value.event) return; el.timer = null
el.handler = function() {
if (el.timer) {
clearTimeout(el.timer);
el.timer = null;
};
el.timer = setTimeout(() => {
binding.value.fn.apply(this, arguments)
el.timer = null;
}, value.delay || 300);
} el.addEventListener(value.event, el.handler)
},
beforeUnmount(el, binding) {
// 在组件卸载前清除定时器,防止内存泄漏
if (el.timer) {
clearTimeout(el.timer);
el.timer = null;
}
el.removeEventListener(binding.value.event, el.handler)
}
}

Debounce.vue

<template>
<div>
<input v-model="inputValue" v-debounce="handleInput" />
</div>
</template> <script setup>
import { ref } from 'vue'; const inputValue = ref(''); const handleInput = {
event: 'input',
fn (event) {
console.log('Debounced Input:', event.target.value);
},
delay: 500
}
</script>

1.3 节流指令

节流是限制执行频率,有节奏的执行,有规律, 更关注过程。一般用于 DOM 操作频次限制,优化性能,如拖拽、滚动、resize 等操作

throttle.js

// //第一次触发不直接执行回调函数
// export default {
// mounted(el, binding) {
// // 至少需要回调函数以及监听事件类型
// if (typeof binding.value.fn !== 'function' || !binding.value.event) return;
// let delay = 200;
// el.timer = null;
// el.handler = function() {
// if (el.timer) return;
// el.timer = setTimeout(() => {
// binding.value.fn.apply(this, arguments)
// el.timer = null;
// }, binding.value.delay || delay);
// }
// el.addEventListener(binding.value.event, el.handler)
// },
// // 元素卸载前也记得清理定时器并且移除监听事件
// beforeUnmount(el, binding) {
// if (el.timer) {
// clearTimeout(el.timer);
// el.timer = null;
// }
// el.removeEventListener(binding.value.event, el.handler)
// }
// }
// //第一次触发直接执行回调函数
export default {
mounted(el, binding) {
// 至少需要回调函数以及监听事件类型
if (typeof binding.value.fn !== 'function' || !binding.value.event) return; let isFirstTrigger = true; // 判断是否是第一次触发
let delay = 200; el.timer = null;
el.handler = function () {
if (el.timer) return; if (isFirstTrigger) {
binding.value.fn.apply(this, arguments); // 第一次触发直接执行回调函数
isFirstTrigger = false;
return;
} el.timer = setTimeout(() => {
binding.value.fn.apply(this, arguments);
el.timer = null;
}, binding.value.delay || delay);
}; el.addEventListener(binding.value.event, el.handler);
},
// 元素卸载前也记得清理定时器并且移除监听事件
beforeUnmount(el, binding) {
if (el.timer) {
clearTimeout(el.timer);
el.timer = null;
}
el.removeEventListener(binding.value.event, el.handler);
},
};

Throttle.vue

<template>
<div>
<h1>Throttle</h1>
<p>Welcome to the Throttle!</p>
<button v-throttle="handleTest">测试</button>
</div>
</template> <script setup>
const handleTest = {
event: 'click',
fn (event) {
console.log('Throttled Click:', event.target);
},
delay: 1000
}
</script> <style scoped> </style>

1.4 resize 指令

resize 在模板中使用该指令来监听元素大小的变化,执行相应的业务逻辑代码

resize.js

import { ref, onMounted, onUnmounted } from 'vue';

export default {
mounted(el, binding) {
const { value: callback } = binding;
const width = ref(0);
const height = ref(0);
console.log('callback',callback)
function handleResize() {
width.value = el.clientWidth;
height.value = el.clientHeight;
callback({ width: width.value, height: height.value });
}
// 监听窗口大小变化,调用 handleResize
window.addEventListener('resize', handleResize); // 初始时调用一次 handleResize
handleResize(); // 在组件卸载前移除事件监听
onUnmounted(() => {
window.removeEventListener('resize', handleResize);
});
}
}
<template>
<div v-resize="resize">
<h1>Resize</h1>
<p>Resize the window to see the effect.</p>
<p>Window width: {{ windowWidth }}</p>
<p>Window height: {{ windowHeight }}</p>
</div>
</template>
<script setup>
import { ref } from 'vue';
const windowWidth = ref(window.innerWidth);
const windowHeight = ref(window.innerHeight);
const resize=(size)=>{
console.log('Window size changed:', size);
} </script>

1.5 滚动加载指令

封装一个滚动加载监听指令,在模板中使用该指令来实现滚动加载的功能

scrollLoad.js

import { onMounted, onUnmounted } from 'vue';

export default {
mounted(el, binding) {
const { fn, distance = 100 } = binding.value;
console.log(fn)
console.log(el)
console.log(distance)
function handleScroll() {
const scrollHeight = el.scrollHeight;
const offsetHeight = el.offsetHeight;
const scrollTop = el.scrollTop;
if (scrollHeight - offsetHeight - scrollTop <= distance) {
fn();
}
} // 监听滚动事件,调用 handleScroll
el.addEventListener('scroll', handleScroll); // 在组件卸载前移除事件监听
onUnmounted(() => {
el.removeEventListener('scroll', handleScroll);
});
}
}

scrollLoad.vue

<template>
<div v-scroll-load="loadMore"
style="overflow: auto; height: 200px;
border: 1px solid #ccc;">
<ul style="height: 500px">
<li v-for="item in items" :key="item">{{ item }}</li>
</ul>
</div>
</template> <script setup>
import { ref } from 'vue'; const items = ref([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]) const loadMore = {
fn() {
// 模拟加载更多数据
for (let i = 0; i < 10; i++) {
items.value.push('Item ' + (items.value.length + 1));
}
},
distance: 100
}
</script>

1.6 图片懒加载指令

在图片元素上使用指令,实现图片的懒加载

lazyLoad.js

export default {
mounted(el, binding) {
// 使用 Intersection Observer 实现图片懒加载
const io = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
el.src = binding.value;
observer.unobserve(el);
}
});
});
io.observe(el);
}
}

lazyLoad.vue

<template>
<div>
<!-- 其他内容 -->
<div class="block">
空白
</div>
<img v-lazy-load="lazyImageSrc" alt="Lazy Image">
</div>
</template> <script setup>
import {ref} from "vue";
const lazyImageSrc = ref('https://img1.baidu.com/it/u=1632607226,1185621596&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=728')
</script>
<style>
.block {
height: 1000px;
}
</style>

1.7 正则指令

开发中遇到的表单输入,往往会有对输入内容的限制,比如不能输入表情和特殊字符,只能输入数字或字母等。

根据正则表达式,设计自定义处理表单输入规则的指令,下面以禁止输入数字为例

regRule.js

export default {
mounted(el) {
let offsetX = 0;
let offsetY = 0; el.addEventListener('mousedown', (e) => {
offsetX = e.clientX - el.getBoundingClientRect().left;
offsetY = e.clientY - el.getBoundingClientRect().top;
document.addEventListener('mousemove', move);
document.addEventListener('mouseup', stop);
}); function move(e) {
el.style.left = `${e.clientX - offsetX}px`;
el.style.top = `${e.clientY - offsetY}px`;
} function stop() {
document.removeEventListener('mousemove', move);
document.removeEventListener('mouseup', stop);
}
}
}

regRule.vue

<template>
<div>
<input tyep="text" v-reg-rule="handleInput">
</div>
</template> <script setup>
import {ref} from "vue";
const handleInput = (value)=>{
console.log('value',value)
} </script>

1.8

在元素上使用指令,实现拖拽功能。

鼠标按下(onmousedown)时记录目标元素当前的 left 和 top 值。

鼠标移动(onmousemove)时计算每次移动的横向距离和纵向距离的变化值,并改变元素的 left 和 top 值

鼠标松开(onmouseup)时完成一次拖拽

draggable.js

export default {
mounted: function (el, binding) {
let offsetX = 0;
let offsetY = 0; el.addEventListener('mousedown', (e) => {
offsetX = e.clientX - el.getBoundingClientRect().left;
offsetY = e.clientY - el.getBoundingClientRect().top;
document.addEventListener('mousemove', move);
document.addEventListener('mouseup', stop);
}); function move(e) {
el.style.left = `${e.clientX - offsetX}px`;
el.style.top = `${e.clientY - offsetY}px`;
} function stop() {
document.removeEventListener('mousemove', move);
document.removeEventListener('mouseup', stop);
}
}
}

Draggable.vue

<template>
<button class="drag" v-draggable>
Drag Me
</button>
</template> <script>
</script>
<style>
.drag{
position: absolute;
}
</style>

1.9 水印指令

给页面添加背景水印。

使用 canvas 特性生成 base64 格式的图片文件,设置其字体大小,颜色等。

将其设置为背景图片,从而实现页面或组件水印效果

waterMarker.js

const addWaterMarker = (str, parentNode, font, textColor) => {
// 水印文字,父元素,字体,文字颜色
let can = document.createElement("canvas");
parentNode.appendChild(can);
can.width = 200;
can.height = 150;
can.style.display = "none";
let cans = can.getContext("2d");
cans.rotate((-20 * Math.PI) / 180);
cans.font = font || "16px Microsoft JhengHei";
cans.fillStyle = textColor || "rgba(180, 180, 180, 0.3)";
cans.textAlign = "left";
cans.textBaseline = "Middle";
cans.fillText(str, can.width / 10, can.height / 2);
parentNode.style.backgroundImage = "url(" + can.toDataURL("image/png") + ")";
}; const waterMarker = {
mounted(el, binding) {
addWaterMarker(binding.value.text, el, binding.value.font, binding.value.textColor);
}
};
export default waterMarker;

warterMarker.vue


<template>
<div
class="content-box"
v-waterMarker="{
text: 'Watermark Direct',
textColor: 'rgba(180, 180, 180, 0.6)'
}"
>
<span class="text">水印指令</span>
</div>
</template> <style scoped >
.content-box {
width: 600px;
height: 600px;
}
</style>

2、源码

2.1 地址

https://github.com/heyu3913/directive

2.2 运行

cd my-vue-app
npm i
npm run dev
ps:本项目采用路由根据文件自动生成,所以大家注意查看路由生成规则'pages/文件名',具体可查看路由文件

3、免费的gpt地址

https://www.hangyejingling.cn/

每日一题:vue3自定义指令大全(呕心沥血所作,附可运行项目源码)的更多相关文章

  1. vue3 自定义指令控制按钮权限

    经过1个周的摸索和查阅资料,终于搞定VUE3中自定义指令,实现按钮级别的权限控制.当然,只是简单的对按钮进行隐藏和删除的dom操作比较容易,一直纠结的是当按钮无权限时,不是直接删除当前dom元素(bu ...

  2. Vue3 自定义指令执行了两次的问题

    下面是我注册全局指令的代码,这是我注册的一个通过 hljs 解析 html -> pre code 的指令,数据是异步获取的: app.directive("parse-code&qu ...

  3. 项目源码--IOS自定义视频播放器

    下载源码 技术要点: 1. 视频播放器功能的实现 2. 视频文件的扫描与管理 3. Ipad UI的实现 4.源码详细的中文注释 ……. 详细介绍: 1. 视频播放器功能的实现 源码基于MediaPl ...

  4. Springboot+Redisson自定义注解一次解决重复提交问题(含源码)

    前言   项目中经常会出现重复提交的问题,而接口幂等性也一直以来是做任何项目都要关注的疑难点,网上可以查到非常多的方案,我归纳了几点如下:   1).数据库层面,对责任字段设置唯一索引,这是最直接有效 ...

  5. 可自定义导航条功能案例ios项目源码

    可定制的navigationitem ,当我们使用系统的方法设置navigationItem的leftItem或者rightItem时,我们会 发现item位置会有偏差(左边的偏右,右边的偏左).当设 ...

  6. jqueryValidator自定义校验规则的一种方式(不覆盖源码)

    1.封装自定义验证方法-validate-methods.js /***************************************************************** j ...

  7. Vue 3自定义指令开发

    本文由葡萄城技术团队原创并首发 转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 什么是指令(directive) 在Angular和Vue中都有Direct ...

  8. vue.js实现内部自定义指令和全局自定义指令------directive

    在Vue中,我们平时数据驱动视图时候,内部自带的指令有时候解决不了一些需求,这时候,Vue给我们一个很好用的东东 directive 这个单词是我们写自定义指令的关键字哦 之定义指令为我们提供了几个钩 ...

  9. Vue | 自定义指令和动态路由实现权限控制

    功能概述: 根据后端返回接口,实现路由动态显示 实现按钮(HTML元素)级别权限控制 涉及知识点: 路由守卫 Vuex使用 Vue自定义指令 导航守卫 前端工程采用Github开源项目Vue-elem ...

  10. Vue.js 源码分析(十四) 基础篇 组件 自定义事件详解

    我们在开发组件时有时需要和父组件沟通,此时可以用自定义事件来实现 组件的事件分为自定义事件和原生事件,前者用于子组件给父组件发送消息的,后者用于在组件的根元素上直接监听一个原生事件,区别就是绑定原生事 ...

随机推荐

  1. 10.1. Java性能调优

    Java性能调优是一个复杂且重要的主题,它涉及到了JVM.垃圾收集器.内存管理.多线程.代码优化等多个方面.在本节中,我们将对Java性能调优的基本概念和方法进行简要介绍. 10.1.1. 理解性能指 ...

  2. WPF 入门笔记 - 06 - 命令

    我们把世界看错,反说它欺骗了我们. --飞鸟集 前言 相较而言,命令对我来说是一个新概念,因为在Winform中压根没有所谓的命令这个概念.从文字角度理解,"命令"可以指代一种明确 ...

  3. C++面试八股文:std::array如何实现编译器排序?

    某日二师兄参加XXX科技公司的C++工程师开发岗位第25面: 面试官:array熟悉吗? 二师兄:你说的是原生数组还是std::array? 面试官:你觉得两者有什么区别? 二师兄:区别不是很大,原生 ...

  4. Python运维开发之路《高阶函数》

    一.列表生成式,迭代器&生成器 列表生成式 需求:data列表里有如下三个值,需要给每个值加1 1 data = [1,2,3] 2 list = map(lambda x:x+1,data) ...

  5. 图书商城项目练习①管理后台Vue2/ElementUI

    本系列文章是为学习Vue的项目练习笔记,尽量详细记录一下一个完整项目的开发过程.面向初学者,本人也是初学者,搬砖技术还不成熟.项目在技术上前端为主,包含一些后端代码,从基础的数据库(Sqlite).到 ...

  6. 【.NET源码解读】深入剖析中间件的设计与实现

    .NET本身就是一个基于中间件(middleware)的框架,它通过一系列的中间件组件来处理HTTP请求和响应.在之前的文章<.NET源码解读kestrel服务器及创建HttpContext对象 ...

  7. Visual Studio Code安装C#开发工具包并编写ASP.NET Core Web应用

    前言 前段时间微软发布了适用于VS Code的C#开发工具包(注意目前该包还属于预发布状态但是可以正常使用),因为之前看过网上的一些使用VS Code搭建.NET Core环境的教程看着还挺复杂的就一 ...

  8. 现代C++(Modern C++)基本用法实践:三、移动语义

    概述 移动 移动(move)语义C++引入了一种新的内存优化,以避免不必要的拷贝.在构造或者赋值的时候,如果实参是右值(或者左值由std::move转换成右值),便会匹配移动语义的函数调用如下述举例的 ...

  9. 【技术积累】HTML+CSS+JavaScript中的基础知识【一】

    HTML基础标签 <html> 定义HTML文档的根元素. <!DOCTYPE html> <html> <head> <title>My ...

  10. 【译】如何在 Visual Studio 中调试异步代码

    虽然异步代码可以提高程序的整体吞吐量,但异步代码仍然无法免除错误!当潜在的死锁.模糊的错误消息以及查找导致 Bug 的 Task 时,编写异步代码会使调试更加困难.幸运的是,Visual Studio ...