【vue3组件封装】Message消息组件

文中涉及的其他组件(SIcon)可在专栏中查询

使用

import { Message } from '@/components'
Message.success("Login successful!")
Message.success("Login successful!",3000) //第二个参数是停留时间 可选

效果

【vue3组件封装】Message消息组件_第1张图片

Types

// 消息样式
type MessageStyle = {
   icon: string;
   color: string;
   backgroundColor: string;
   borderColor: string;
};

type MessageStyleKeys = "info" | "success" | "warn" | "error"; // 支持的类型

export interface IMessageStyle {
   [index in MessageStyleKeys]: MessageStyle;
   [index: string]: MessageStyle;
}

常量

// 停留时间
export const MESSAGE_TIMEOUT: number = 3000;
// message样式
// 这里的icon是自己在iconfont找的,名称与其对应,详细可参考本专栏的“Icon图标组件”文章
export const MESSAGE_STYLE: IMessageStyle = {
   warn: {
      icon: "icon-warn-fill",
      color: "#E6A23C",
      backgroundColor: "#fff7e6",
      borderColor: "#ffe7ba",
   },
   error: {
      icon: "icon-error-fill",
      color: "#F56C6C",
      backgroundColor: "#fff1f0",
      borderColor: "#ffccc7",
   },
   success: {
      icon: "icon-success-fill",
      color: "#67C23A",
      backgroundColor: "#f6ffed",
      borderColor: "#d9f7be",
   },
   info: {
      icon: "icon-info-fill",
      color: "#40a9ff",
      backgroundColor: "#e6f7ff",
      borderColor: "#bae7ff",
   },
};

封装

消息组件:SMessage/SMessage.vue

<template>
    <--!自定义动画-->
    <transition name="fade">
        <div class="s-message" :style="MESSAGE_STYLE[props.type]" v-if="isShow">
            <s-icon :icon="MESSAGE_STYLE[props.type].icon" />
            <span class="text">{{ props.text }}span>
        div>
    transition >
template>

<script lang="ts" setup>
import { MESSAGE_TIMEOUT, MESSAGE_STYLE } from "@/utils" // 参见上面的常量
import { SIcon } from "@/components"
import { ref, onMounted } from "vue"
const props = defineProps({
  // 消息文本
  text: {
    type: String,
    default: ""
  },
  // 消息类型: "info" | "success" | "warn" | "error"
  type: {
    type: String,
    default: "warn" 
  },
  // 消息停留时间
  timeout: {
    type: Number,
    default: MESSAGE_TIMEOUT
  }
})

// 组件状态
const isShow = ref<boolean>(false)

// 注册定时器控制组件的消失
onMounted(() => {
  isShow.value = true
  setTimeout(() => {
    isShow.value = false
  }, props.timeout)
})
script>

<style scoped lang="less">
.fade-enter-active{
  animation: fade .5s;
}
.fade-leave-active {
  animation: fade .5s reverse;
}

/* 定义帧动画 */
@keyframes fade {
  0% {
    opacity: 0;
    transform: translateY(-50px);
  }

  100% {
    opacity: 1;
  }
}

.s-message {
    min-width: 300px;
    max-width: 350px;
    padding: 8px @itemSpace;
    position: fixed;
    z-index: 9999;
    left: 50%;
    margin-left: -150px;
    top: 25px;
    border-radius: 4px;
    .text {
        vertical-align: middle;
    }
}
style>

调用后挂载消息组件:SMessage/index.ts

import { MESSAGE_TIMEOUT } from "@/utils" 
import { createVNode, render } from 'vue'
import SMessage from './SMessage.vue'

const div = document.createElement('div')
// 添加到body上
document.body.appendChild(div)

// 定时器标识
let timer: any = null

const renderMessage = (vnode: any, timeout: number) => {
   render(null, div);// 清空上一个虚拟dom
   render(vnode, div);
   clearTimeout(timer);// 清理上一个定时器
   timer = setTimeout(() => {
      render(null, div);
   }, timeout);
};

// 根据不同的调用创建虚拟dom
export default {
   error: (text: string, timeout: number = MESSAGE_TIMEOUT) => {
      const vnode = createVNode(SMessage, { type: "error", text, timeout });
      renderMessage(vnode, timeout);
   },
   warn: (text: string, timeout: number = MESSAGE_TIMEOUT) => {
      const vnode = createVNode(SMessage, { type: "warn", text, timeout });
      renderMessage(vnode, timeout);
   },
   success: (text: string, timeout: number = MESSAGE_TIMEOUT) => {
      const vnode = createVNode(SMessage, { type: "success", text, timeout });
      renderMessage(vnode, timeout);
   },
   info: (text: string, timeout: number = MESSAGE_TIMEOUT) => {
      const vnode = createVNode(SMessage, { type: "info", text, timeout });
      renderMessage(vnode, timeout);
   },
};


你可能感兴趣的:(组件封装,vue.js,javascript,前端)