当前位置: 首页 > news >正文

vue2企业级项目(六)

vue2企业级项目(六)

自定义指令

  1. 创建src/directive/index.js

    const directives = require.context("./modules", true, /\.js$/);export default {install: (Vue) => {directives.keys().forEach((key) => {let directive = directives(key).default;let name = key.replace(/^\.\/(.*)\.\w+$/, "$1");directive && Vue.directive(name, directive);});},
    };
  2. main.js注入使用

    import directives from "./directive";...Vue.use(directives);
    
  3. 创建src/directive/modules目录

1、v-loading

element-ui有,就不需要

2、v-draggable

创建src/directive/draggable.js

import { checkDataType } from "@/utils/utils";
let recoverStyle = null;export default {update(el, binding) {let config = binding.value;let visible = false;let target = ".el-dialog__header";let control = ".el-dialog";if (checkDataType(config, "object")) {visible = config.visible;target = config.target;control = config.control;} else {visible = config;}const dialogHeaderEl = el.querySelector(target);const dragDom = el.querySelector(control);dialogHeaderEl.style.cursor = "move";function readStyle(dom, attr) {if (document.body.currentStyle) return dom.currentStyle[attr];return getComputedStyle(dom, false)[attr];}if (visible) {recoverStyle = {left: readStyle(dragDom, "left"),top: readStyle(dragDom, "top"),margin: readStyle(dragDom, "margin"),};dialogHeaderEl.onmousedown = function(e) {// 获取鼠标相对当前元素内部位置const disX = e.clientX - dragDom.offsetLeft;const disY = e.clientY - dragDom.offsetTop;// 获取当前窗口视图大小const screenWidth = document.body.clientWidth;const screenHeight = document.documentElement.clientHeight;// 获取当前元素大小const dragDomWidth = dragDom.offsetWidth;const dragDomheight = dragDom.offsetHeight;// 计算获取最大偏移量const maxLeft = screenWidth - dragDomWidth;const maxTop = screenHeight - dragDomheight;document.onmousemove = function(e) {let left = e.clientX - disX;let top = e.clientY - disY;// 碰撞判断if (left <= 0) left = 0;if (left >= maxLeft) left = maxLeft;if (top <= 0) top = 0;if (top >= maxTop) top = maxTop;left = ((left * 100) / screenWidth).toFixed(2) + "%";top = ((top * 100) / screenHeight).toFixed(2) + "%";dragDom.style.left = left;dragDom.style.top = top;dragDom.style.margin = 0;};document.onmouseup = function() {document.onmousemove = null;document.onmouseup = null;};};} else {// 还原初始化的样式dragDom.style.left = recoverStyle.left;dragDom.style.top = recoverStyle.top;dragDom.style.margin = recoverStyle.margin;dialogHeaderEl.onmousedown = null;recoverStyle = null;}},
};

3、v-click-outside

创建src/directive/click-outside.js

export default {bind(el, binding) {// 点击事件回调函数const onClickOutside = (event) => {if (!(el === event.target || el.contains(event.target))) {binding.value(event);}};// 将回调函数绑定到元素上el._clickOutsideCallback = onClickOutside;// 添加点击事件监听器document.addEventListener("click", onClickOutside);},unbind(el) {// 移除点击事件监听器document.removeEventListener("click", el._clickOutsideCallback);delete el._clickOutsideCallback;},
};

4、v-ripple(简单的)

创建src/directive/ripple.js

function createRipple(el, radius, color, disX, disY) {new Promise((resolve) => {const rippleDom = document.createElement("span");rippleDom.className = "ripple";rippleDom.setAttribute("style",`display: block;position: absolute;border-radius: 50%;transform: translate(-50%, -50%) scale(0);transition: 0.5s;background-color: ${color || "rgba(0, 0, 0, 0.6)"};top: ${disY}px;left: ${disX}px;width: ${radius * 3}px;height: ${radius * 3}px;animation: ripple-animation 0.5s linear;`,);el.appendChild(rippleDom);let timer = setTimeout(() => {el.removeChild(rippleDom);resolve(timer);}, 520);}).then((timer) => {clearTimeout(timer);});
}function rippleShow(e) {const targetDom = e.target;const radius =targetDom.offsetHeight > targetDom.offsetWidth? targetDom.offsetHeight: targetDom.offsetWidth;const disX = e.clientX - targetDom.offsetLeft;const disY = e.clientY - targetDom.offsetTop;createRipple(targetDom, radius, e?._ripple, disX, disY);
}export default {bind(el, binding) {el._ripple = binding.value;el.style.position = "relative";el.style.overflow = "hidden";el.style.userSelect = "none";el.addEventListener("mousedown", rippleShow);},unbind(el) {el._ripple = null;el.removeEventListener("mousedown", rippleShow);},
};

创建src/styles/animation.less,并在scr/styles/index.less内引入

// ripple动画
@keyframes ripple-animation {to {transform: translate(-50%, -50%) scale(1);opacity: 0;}
}

5、v-intersect

交叉观察者

创建src/directive/intersect.js

export default {bind(el, binding) {let info = null;let callback = null;if (typeof binding.value === "object") {info = binding.value?.info;callback = binding.value?.callback;} else {callback = binding.value;}const observer = new IntersectionObserver((entries) => {entries.forEach((entry) => {if (entry.isIntersecting) {callback && callback(info);}});},{ root: el.parentElement },);observer.observe(el);},
};

6、v-scroll

滚动监听

创建src/directive/scroll.js

export default {bind(el, binding) {el.onscroll = function() {binding.value({x: el.scrollLeft,y: el.scrollTop,});};},unbind(el) {el.onscroll = null;},
};

7、v-scroll-to

滚动设置

创建src/directive/scroll-to.js

export default {update(el, binding) {let x = binding.modifiers?.x || false;if (binding.value && binding.value === binding.oldValue) return;if (typeof binding.value === "number") {x ? (el.scrollLeft = binding.value) : (el.scrollTop = binding.value);} else if (typeof binding.value === "string") {let targetDom = document.querySelector(binding.value);if (x) {let border = getComputedStyle(el, false)["borderLeftWidth"];let padding = getComputedStyle(el, false)["paddingLeft"];border = border.replace("px", "");padding = padding.replace("px", "");el.scrollLeft = targetDom.offsetLeft - el.offsetLeft - border - padding;} else {let border = getComputedStyle(el, false)["borderTopWidth"];let padding = getComputedStyle(el, false)["paddingTop"];border = border.replace("px", "");padding = padding.replace("px", "");el.scrollTop = targetDom.offsetTop - el.offsetTop - border - padding;}}},
};

8、v-auto-scroll

自动滚动

创建src/directive/scroll-auto.js

function active(el, scroll, step, max, x) {window.requestAnimationFrame(() => {x ? (el.scrollLeft = scroll) : (el.scrollTop = scroll);scroll += step;if (scroll >= max) scroll = 0 + step;active(el, scroll, step, max, x);});
}export default {inserted(el, binding) {const x = binding.modifiers?.x || false;let step = 0;let scroll = 0;if (typeof binding.value === "object") {step = binding.value?.step || 5;scroll = binding.value?.begin || 0;} else {step = binding.value || 5;}const scrollMax = x ? el.scrollWidth : el.scrollHeight;el._children = [].slice.call(el.children);el._children.forEach((child) => {el.appendChild(child.cloneNode(true));});active(el, scroll, step, scrollMax, x);},unbind(el) {el.innerHtml = "";let children = [].slice.call(el.children);children.forEach((child) => {el.removeChild(child);});el._children.forEach((child) => {el.appendChild(child.cloneNode(true));});},
};

http://www.lryc.cn/news/99438.html

相关文章:

  • OSPF的选路原则
  • 4.操作元素属性
  • uniapp 微信小程序:v-model双向绑定问题(自定义 props 名无效)
  • 【Lua学习笔记】Lua进阶——Table(3) 元表
  • AI编程常用工具 Jupyter Notebook
  • RocketMQ重复消费的解决方案::分布式锁直击面试!
  • 如何降低TCP在局域网环境下的数据传输延迟
  • 【LeetCode】78.子集
  • 认可功能介绍 - 技术声誉靠认可
  • EtherNet/IP转CAN网关can协议标准
  • 解决代理IP负载均衡与性能优化的双重挑战
  • 深度探索 Elasticsearch 8.X:function_score 参数解读与实战案例分析
  • 测牛学堂:软件测试之andorid app性能测试面试知识点总结(二)
  • 尚医通06:数据字典+EasyExcel+mongodb
  • 【前端知识】React 基础巩固(三十二)——Redux的三大原则、使用流程及实践
  • [NLP]使用Alpaca-Lora基于llama模型进行微调教程
  • Linux Shell 脚本编程学习之【第5章 文件的排序、合并与分割 (第四部分之cut命令) 】
  • php-golang-rpc jsonrpc和php客户端tivoka/tivoka包实践
  • flutter 打包iOS安装包
  • 二进制重排
  • 【Linux后端服务器开发】MAC地址与其他重要协议
  • WebGPU入门
  • React Dva项目中.roadhogrc.mock.js直接自动导入mock目录下所有文件方式
  • 跨境独立站如何应对恶意网络爬虫?
  • C# SourceGenerator 源生成器初探
  • 网络安全/信息安全—学习笔记
  • 【Visual Studio】无法打开包括文件: “dirent.h”: No such file or directory
  • asp.net MVC markdown编辑器
  • 论文浅尝 | 预训练Transformer用于跨领域知识图谱补全
  • 算法工程师-机器学习面试题总结(2)