基于vue3组件开发--toast

817 阅读1分钟

组件库简单开发之--toast

直接上代码:

// index.ts
import { createApp,nextTick,ComponentPublicInstance } from 'vue'
import ToastComponent from './index.vue'
export type ToastOptions = {
    iconName?: string,
    message?: String,
    duration?: Number,
}
export type ComponentInstance = ComponentPublicInstance<{}, any>;
let toastPool:ComponentInstance[] = []
function createInstance() {
    const app = createApp(ToastComponent);
    const root = document.createElement('div');
    document.body.appendChild(root);
    const instance = app.mount(root)
    return instance
}
function getInstance(){
    if (!toastPool.length) {
        const instance = createInstance();
        toastPool.push(instance);
    }
    return toastPool[toastPool.length - 1];
}
function parseOptions(message: string | ToastOptions): ToastOptions {
    if(message !== null && typeof message === 'object'){
        return message;
    }
    return { message }
}
function Toast(options: string | ToastOptions = {}){
    const toast = getInstance();
    const parsedOptions:ToastOptions = parseOptions(options);
    Object.assign(toast,parsedOptions)
    nextTick(()=> {
        toast.visible = true
        setTimeout(()=>{
            toast.close()
        }, toast.duration)
    })
    return toast
}
// 延申方法todo
Toast.success=()=>{}
Toast.fail=()=>{}
Toast.loading=()=>{}
export default Toast
// index.vue
<template>
  <div class="le-toast" v-show="visible">
    <div class="le-toast-box">
      <le-icon class="icon" v-if="iconName" size="40px" :name="iconName" />
      <span class="message">{{ message }}</span>
    </div>
  </div>
</template>
<script lang="ts">
import { defineComponent,toRefs,reactive} from 'vue'
import LeIcon from '@ui/base/icon'
export default defineComponent({
    name:'le-toast',
    components: { LeIcon },
    setup() {
        const data = reactive({
            visible:false,
            iconName:'',
            message:'',
            duration:2000,
            close:()=>{
                data.visible = false
            }
        })
        const toRafsData = toRefs(data)
        return {
            ...toRafsData
        }
    }
})
</script>
<style lang="less">
@import './index.less';
</style>
// index.less
@import '@assets/style/var.less';
.le-toast {
  position: fixed;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  bottom: inherit !important;
  min-width: 320px;
  max-width: 750px;
  margin: 0 auto;
  box-sizing: border-box;
  z-index: 1001;
  text-align: center;

  &-box {
    width: auto;
    background: rgba(0, 0, 0, 0.7);
    border-radius: 8px;
    padding: 20px;
    font-size: 13px;
    max-width: 282px;
    color: #fff;
    display: inline-block;
    word-break: break-all;
    margin: 0 auto;
    text-align: center;

    .icon {
      display: block;
      font-size: 26px;
      padding: 2px;
      margin-bottom: 8px;
    }

    .message {
      font-size: 14px;
      display: block;
    }
  }
}
import Toast from "@ui/base/toast/index"
app.config.globalProperties.$Toast = Toast
// 使用方式
$Toast('提示信息提示信息');
$Toast({
    message:'提示+图标',
    duration:4000,
    iconName:'success'
})

效果

image.png image.png