首页>>前端>>Vue->Vue3 TypeScript 全局 Message 提示框

Vue3 TypeScript 全局 Message 提示框

时间:2023-11-29 本站 点击:0

前言

实现过一个 vue2 + ts 下的全局的 Message 提示框。闲暇之余想在 vue3 + ts 的框架下也实现此功能。

技术思路

在 vue3 上的实现思路

install 函数是把编写的 Message 组件实例化并渲染到页面的关键。其中的步骤:

根据 Message 组件实例化一个 Message

在 document.body 上 appendChild 实例

同时返回一个 destory 函数用于手动销毁实例

倒计时时间到销毁实例

编写 Message 组件代码

//Mssage.vue<template><transitionname="slide"><div:class="[type,center?'text-center':'']":style="{...style}"v-if="visible"><divv-if="messageArr.length"><divv-for="(item,index)inmessageArr":key="index">{{item}}</div></div><divv-else>{{message}}</div></div></transition></template><script>import{defineComponent}from'vue';exportdefaultdefineComponent({props:{message:{type:String,default:'',},type:{type:String,default:'success',},duration:{type:Number,default:2000,},},data(){constmessageArr:Array<string>=[];conststyle={};return{messageArr,visible:true,center:false,style,};},created():void{constarr=this.message.split('\n');if(arr.length>1){this.messageArr=arr;}},mounted():void{this.startTimer();},methods:{startTimer():void{const{duration}=this;consttimer=setTimeout(()=>{this.visible=false;clearTimeout(timer);},duration);},},});</script>

编写 install 函数并挂载到 vue 全局

//index.tsimport{App,render,createVNode}from'vue';importMessagefrom'./Message.vue';constdefaultOpt={//创建默认参数duration:2000,type:'success',};//消息数组conststack:Array<HTMLDivElement>=[];/***@description:销毁body上的Message实例*@param{HTMLDivElement}ele*@return{*}*/constremoveContainer=(ele:HTMLDivElement):void=>{constindex=stack.findIndex((item)=>item===ele);if(~index){stack.splice(index,1);setStyle();}};/***@description:把实例加到实例队列stack中,并设置队列中搜有实例的style*@param{HTMLDivElement}ele*@return{*}*/constaddContainer=(ele:HTMLDivElement):void=>{stack.push(ele);setStyle();};/***@description:设置stack中所有实例的style*@param{*}*@return{*}*/constsetStyle=()=>{stack.forEach((item,index)=>{if(item?.getElementsByClassName('message-wrap')?.[0]){lettop=0;if(index>0){top+=(stack[index-1].getElementsByClassName('message-wrap')[0]asHTMLElement)?.getBoundingClientRect()?.bottom||0;}//eslint-disable-next-line(item.getElementsByClassName('message-wrap')[0]asHTMLElement).style.marginTop=`${top}px`;}});};//创建挂载实例//eslint-disable-next-lineconstcreateMount=(opts:{[key:string]:any})=>{const{duration}=opts;//创建一个div容器constcontainer=document.createElement('div');//创建Message实例,createVNode的性能比h更好constvm=createVNode(Message,opts);//把实例render到容器上render(vm,container);addContainer(container);//把容器渲染到body上document.body.appendChild(container);constdestory=()=>{consttimer=setTimeout(()=>{render(null,container);removeContainer(container);document.body.removeChild(container);clearTimeout(timer);},500);//500为动画结束时间,根据情况修改};consttimer=setTimeout(()=>{destory();clearTimeout(timer);},duration||defaultOpt.duration);return{destory};};functionToast(options:{message:string;duration?:number}|string):{destory:()=>void;}{if(typeofoptions==='string'){//eslint-disable-next-lineoptions={...defaultOpt,message:options||'',};}else{//eslint-disable-next-lineoptions={...defaultOpt,...options,};}returncreateMount(options);}Toast.install=(app:App<Element>)=>{app.component('toast',Message);app.provide('Toast',Toast);//挂载Toast为全局方法$toast//eslint-disable-next-lineapp.config.globalProperties.$toast=Toast;};exportdefaultToast;

use 为全局组件;增加 $toast 声明,消除使用时的 ts 报错

import{createApp}from'vue';importToastfrom'@/components/toast';constapp=createApp(App);app.use(Toast);app.mount('#app');//定义了全局方法之后需要扩充类型declaremodule'@vue/runtime-core'{interfaceComponentCustomProperties{$toast:typeofToast;}}

使用

this.$toast('message');this.$toast({message:'message',dutation:5000,})

和 vue2 上的对比

vue2vue3创建方式1. 先创建构造函数 const MessageBox = Vue.extend(MessageComp); 2. 通过构造函数实例化对象 const instance: any = new MessageBox({ data: options, }).$mount();1. 先创建一个 div 容器 const container = document.createElement('div'); 2. createVNode 创建组件实例 const vm = createVNode(Message, opts); 3. 把实例 render 到容器上 render(vm, container);

tips

vue2 版本?:https://juejin.cn/post/7015199722805657631


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