vue3常用指令以及注册

发布时间:2026/5/19 4:37:18

vue3常用指令以及注册 vue3 常用指令以及注册简单梳理一些 vue3 常用指令以及用法vue3 工程化搭建vue3 工程化搭建这里用的是 vite 作为构建工具搭建步骤如下导入各个模块路由router.js 文件// 引入各模块路由letmoduleRouters[]constrcimport.meta.globEager(./modules/*.js);moduleRoutersObject.keys(rc).reduce((modules,key)modules.concat(rc[key].default),[]);constroutes[...moduleRouters];exportdefaultroutes;// modules文件夹// F下引入各模块路由constrcimport.meta.globEager(../../modules/*/router/index.js)constrouterObject.keys(rc).reduce((modules,key){constnamekey.replace(/(\..\/\..\/modules\/)|(\/router\/index\.js$)/g,)returnmodules.concat(rc[key].default.map(i{i.path/${name}${i.path}returni}))},[])exportdefaultrouter应用入口文件main.js 文件importWebInitfrom./webInit;importrouterfrom./router;// 引入路由配置文件,各个模块的路由配置文件constwebnewWebInit({router});web.init();main.js 使用初始化实例webInit.js 文件//引入elementui plus组件import{resetMessage}from./msg;import*asElementPlusIconsVuefromelement-plus/icons-vue;importElementPlusfromelement-plus;//引入自定义公共组件importGlobalCpnfrom./global/globalCpn;// 引入自定义mixin方法importmixinsfrom./mixins;// 引入全局工具方法importGlobalFnfrom./tools/fn;// 全局storeimportstorefrom./store/index;//全局指令importdirectiveListfrom./directive;// 权限控制,路由守卫,判断用户权限,动态添加路由import./permission;//静态路由importrouterfrom./router;importelement-plus/dist/index.css;//引入全局SCSSimport./styles/index.scss;//引入iconimport./assets/iconfonts/iconfont.css;import./assets/iconfonts/iconfont.js;import./assets/icons/index.js;//引入字体import./assets/font/font.css;//国际化importenfrom./assets/langs/en.js;importzh_cnfrom./assets/langs/zh-CN.js;importzhCnfromelement-plus/es/locale/lang/zh-cn;import{createI18n}fromvue-i18n;import{createApp}fromvue;importAppfrom./views/App.vue;importvirtual:svg-icons-register;consti18nnewcreateI18n({// 设置默认语言locale:zh_cn,// 语言标识// 添加多语言每一个语言标示对应一个语言文件messages:{zh_cn,en,},});exportdefaultclassWebInit{constructor({router}){this.appcreateApp(App);this.routesrouter;}asyncinit(){this.routes.forEach((i)router.addRoute(i));//动态添加路由配置文件中的路由规则到router实例中this.app.mixin(mixins)//全局mixin注册.use(router)//注册路由实例到vue中.use(store)//注册store实例到vue中.use(ElementPlus,{locale:zhCn}).use(GlobalCpn)//全局组件注册.use(i18n);//国际化注册// 注册element-plus图标组件for(const[key,component]ofObject.entries(ElementPlusIconsVue)){this.app.component(key,component);}//注册指令for(letjindirectiveList){this.app.directive(j,directiveList[j]);}// 全局方法注册this.app.config.globalProperties.$fnGlobalFn;// 挂载到 #app 上this.app.mount(#app);}}全局组件注册文件全局组件注册文件,自动导入 global 目录下所有 index.vue 文件并以 g-开头命名注册到 Vue 中,GlobalCpn.js 文件示例如下!-- global/Echarts/index.vue -- template div :styleprops.style ? props.style : { zoom: 1 / zoom } :classprops.style ? : echart w100 h100 refchartDom /div /template script setup nameecharts import { debounce } from ./fn; import { ref, onMounted, onBeforeUnmount, watch, nextTick, onBeforeMount, } from vue; import * as echarts from echarts; const props defineProps({ style: { type: Object, default: null, }, option: { type: Object, default: null, }, }); const emit defineEmits([imageUrl]); const chartDom ref(); //图表容器dom元素 let myChart null; //图表实例 const zoom ref(1); //缩放比例 // 防抖 function debounce(fn, delay) { let timer null; return (e) { if (timer) clearTimeout(timer); timer setTimeout(() { fn(e); }, delay); }; } // 节流 function throttle(fn, delay 100) { let flag false; return (e) { if (flag) return; fn(e); setTimeout(() { flag true; }, delay); }; } //重绘图表函数 const resizeHandler () { myChart.resize(); }; // 获取echart图表的图片 const getImageUrl () { let imgSrc myChart.getDataURL(); emit(imageUrl, imgSrc); }; //设置防抖保证无论拖动窗口大小只执行一次获取浏览器宽高的方法 const cancalDebounce debounce(resizeHandler, 300); //页面成功渲染开始绘制图表 onMounted(() { //配置为 svg 形式预防页面缩放而出现模糊问题图表过于复杂时建议使用 Canvas myChart echarts.init(chartDom.value, null, { renderer: svg }); myChart.setOption(props.option, true); window.addEventListener(resize, cancalDebounce); }); onBeforeMount(() { zoom.value document.getElementsByTagName(body)[0].style.zoom; // console.log(zoom.value, zoom); }); //页面销毁前销毁事件和实例 onBeforeUnmount(() { window.removeEventListener(resize, cancalDebounce); myChart.dispose(); }); //监听图表数据时候变化重新渲染图表 watch( () props.option, () { myChart.setOption(props.option, true); myChart.resize(); }, { deep: true } ); defineExpose({ getImageUrl, cancalDebounce, resizeHandler, }); /scriptconstrequireContextimport.meta.globEager(./**/index.vue);constmodulesObject.keys(requireContext).reduce((total,i){constnamei.replace(/(\.\/.)|(\/index\.vue$)|(\/.)|[A-Z]/g,(str){return/(\/index\.vue$)/.test(str)?:-${str.slice(-1).toLowerCase()};});total[g${name}]requireContext[i].default;returntotal;},{});exportdefault{install(vue){Object.keys(modules).forEach((i){vue.component(i,modules[i]);});},};// global目录下为全局组件,只注册目录下所有index.vue// 使用规则: 以./global/preview/index.vue 为例, 用g-preview/指令文件例如utils/directives.js,代码示例如下//指令import{isJSON}from./fn;import{resetMessage}from./msg.js;import{Drag}from./drag;//-------元素里面的input框聚焦------------constfocus{mounted(el){letitem;if(el.tagName!INPUT){itemel.querySelector(input);}else{itemel;}item.focus();},};//-----点击除自己本身的元素外的空白处触发事件---------/** * 传入一个函数 */constclickoutside{// 初始化指令beforeMount(el,binding,vnode){functiondocumentHandler(e){// 这里判断点击的元素是否是本身是本身则返回if(el.contains(e.target)){returnfalse;}// 判断指令中是否绑定了函数if(typeofbinding.valuefunction){// 如果绑定了函数 则调用那个函数此处binding.value就是handleClose方法binding.value(e);}}// 给当前元素绑定个私有变量方便在unbind中可以解除事件监听el.__vueClickOutside__documentHandler;document.addEventListener(click,documentHandler);},unmounted(el,binding){// 解除事件监听document.removeEventListener(click,el.__vueClickOutside__);deleteel.__vueClickOutside__;},};//-----------复制元素------------------/** * 传入要复制的内容 */constcopy{mounted(el,{value}){el.$valuevalue;// el控件定义 onclick 事件el.onclick(){if(!el.$value){console.log(无复制内容);return;}// 动态创建 textarea 标签consttextareadocument.createElement(textarea);// 将该 textarea 设为 readonly 防止 iOS 下自动唤起键盘同时将 textarea 移出可视区域textarea.readOnlyreadonly;textarea.style.positionabsolute;textarea.style.left-9999px;// 将要 copy 的值赋给 textarea 标签的 value 属性if(isJSON(el.$value)||typeofel.$valueobject){textarea.valueJSON.stringify(el.$value);}else{textarea.valueel.$value;}// 将 textarea 插入到 body 中document.body.appendChild(textarea);// 选中值并复制textarea.select();constresultdocument.execCommand(Copy);if(result){resetMessage({type:success,message:已复制,});console.log(复制成功);}document.body.removeChild(textarea);};// 绑定点击事件就是所谓的一键 copy 啦el.addEventListener(click,el.handler);},// 当传进来的值更新的时候触发beforeUpdate(el,{value}){el.$valuevalue;},// 指令与元素解绑的时候移除事件绑定unmounted(el){el.removeEventListener(click,el.handler);},};//-----------将子项变为可拖拽------------------/** * 传入true or false */constdrag{mounted(el,{value},vnode){// 指令绑定到元素时调用if(!!valuetrue){constonDragChangevnode.props[on:dragChange]??((){});el.dragnewDrag(el);el.drag.ondragendonDragChange;}},updated(el,{value},vnode){// 元素更新前调用if(!!valuefalseel.drag){el.drag?.distroy();el.dragnull;}elseif(!!valuetrue){constonDragChangevnode.props[on:dragChange]??((){});el.dragnewDrag(el);el.drag.ondragendonDragChange;}},beforeUnmount(el){// 元素解绑时调用el.drag?.distroy();el.dragnull;},};/** * 只能输入正整数 */constint{mounted(el){el.addEventListener(keypress,function(e){ee||window.event;letcharcodetypeofe.charCodenumber?e.charCode:e.keyCode;letre/\d/;if(!re.test(String.fromCharCode(charcode))charcode9!e.ctrlKey){if(e.preventDefault){e.preventDefault();}else{e.returnValuefalse;}}});},};/** * 只能输入正数(包含小数) */constfloat{mounted(el){el.addEventListener(keypress,function(e){ee||window.event;letcharcodetypeofe.charCodenumber?e.charCode:e.keyCode;letre/^[-]?\d*$/;if(charcode46){if(el.value.includes(.)){e.preventDefault();}return;}elseif(!re.test(String.fromCharCode(charcode))charcode9!e.ctrlKey){if(e.preventDefault){e.preventDefault();}else{e.returnValuefalse;}}});},};constdraggable{mounted(el){el.style.pointerEventsnull;document.body.style.userSelectauto;constheaderel.querySelector(.header);constcontainerel.querySelector(.container);header.style.cssText;cursor:move;;letisDraggingfalse;// 是否正在拖拽// 鼠标点击事件的回调functionmouseDown(e){letXe.clientX-el.offsetLeft;letYe.clientY-el.offsetTop;functionmouseMove(e){isDraggingtrue;// 正在拖拽// el.style.pointerEvents nonedocument.body.style.userSelectnone;el.style.lefte.clientX-Xpx;// 水平边界判断if(el.offsetLeft0)el.style.left0px;if(el.offsetLeftdocument.documentElement.clientWidth-el.offsetWidth)el.style.leftdocument.documentElement.clientWidth-el.offsetWidthpx;// 垂直边界判断el.style.tope.clientY-Ypx;if(el.offsetTop0)el.style.top0px;if(el.offsetTopdocument.documentElement.clientHeight-el.offsetHeight)el.style.topdocument.documentElement.clientHeight-el.offsetHeightpx;}// 注意以下是用 document而不是 el 本身// 这是为了防止 el 跟不上鼠标移动的速度从而导致鼠标脱离了 el 但又没有释放// 添加鼠标移动事件document.addEventListener(mousemove,mouseMove);// 添加鼠标松开事件document.addEventListener(mouseup,(e){el.style.pointerEventsnull;document.body.style.userSelectauto;// 使用延时器在鼠标释放后的一小段时间内保持 isDragging 为 truesetTimeout((){isDraggingfalse;},50);document.removeEventListener(mousemove,mouseMove);});}// 添加鼠标按下事件// el.addEventListener(mousedown, mouseDown);header.addEventListener(mousedown,mouseDown);// 只有头部可拖拽el.addEventListener(click,(e){if(isDragging){e.stopImmediatePropagation();e.preventDefault();}},true);},};exportdefault{focus,clickoutside,copy,drag,int,float,draggable,};

相关新闻