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

news/发布时间2024/5/18 11:58:14

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 = nullel.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 });}// 监听窗口大小变化,调用 handleResizewindow.addEventListener('resize', handleResize);// 初始时调用一次 handleResizehandleResize();// 在组件卸载前移除事件监听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();}}// 监听滚动事件,调用 handleScrollel.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><divclass="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/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ulsteruni.cn/article/31272552.html

如若内容造成侵权/违法违规/事实不符,请联系编程大学网进行投诉反馈email:xxxxxxxx@qq.com,一经查实,立即删除!

相关文章

2023数据采集与融合技术实践作业一

作业1 实验要求 具体要求 用requests和BeautifulSoup库方法定向爬取给定网址的数据,屏幕打印爬取的大学排名信息。 输出信息排名 学校名称 省市 学校类型 总分1 清华大学 北京 综合 852.52...具体代码 import bs4 as bs import urllib.requesturl = "https://www.shangha…

shiro-721 CVE-2019-12422

漏洞描述Apache Shiro是一个强大易用的Java安全框架,提供了认证、授权、加密和会话管理等功能。Shiro框架直观、易用,同时也能提供健壮的安全性。Apache Shiro框架提供了记住密码的功能(RememberMe),用户登录成功后会生成经过加密并编码的cookie。在服务端对rememberMe的c…

CentOS环境 nginx配置vue项目

nginx配置vue项目ps: 这里使用ruoyi-vue-plus项目举例,官网:https://plus-doc.dromara.org/ 一、配置不带应用路径的vue项目 1、打包。首先将vue项目生产配置文件的的应用访问路径设为/,然后命令行输入run run build:prod进行打包。2、导入环境。将打包文件(dist)拖入Cent…

2020ICPC区域赛南京站

2020ICPC区域赛南京站 K Co-prime Permutation 解题思路: 首先,根据样例2不难发现,\(k\)的下界为\(1\),因为1和排列中的任何数都会互质。 其次,我们考虑下上界大概是多少,也就是\(k = n\)是否一定合法。 假设,我们有一个初识排列\(p_i = i\).此时我们有\(1\)个元素和他的…

Odoo看板视图实践案例

看板视图是一个很常见的可视化解决方案了,例如:联系人卡片,任务卡片,还有二次元朋友们经常逛的哔站。 我个人也是非常喜欢看板视图,比起那些呆板的tree视图,看板视图给人的感觉的就是简洁直观又好看。 本人也是初学Odoo一个月,其中深意只知其一,但也想跟各位大佬分享交…

在线问诊 Python、FastAPI、Neo4j — 创建 饮食节点

目录饮食数据创建节点 根据疾病、症状,判断出哪些饮食不能吃,哪些建议多吃 饮食数据 foods_data.csv 建议值用“”引起来。避免中间有,号造成误识别 饮食 "辣椒" "大蒜" "芥末" "海鲜" "胡萝卜" "核桃仁" &quo…