nuxt3+vue3+typescript里写一个全局提示框toast插件

2022-02-21 06:44
椰子皮
2521
1
6
nuxt

nuxt3发布正式版即将来到,那么在nuxt3里面如何封装一个全局插件呢

nuxt3发布正式版即将来到,那么在nuxt3里面如何封装一个全局插件呢,这里就拿一个全局提示框举例吧

效果:

首先在项目根目录建一个plugins文件夹

结构如下:

plugins/index.ts

plugins/message/index.ts

plugins/message/index.vue

 

plugins/message/index.vue代码

<script setup lang="ts">
type MessageType = 'default' | 'success' | 'warning' | 'error'

interface MessageProps {
  tips?: string,
  type?: MessageType,
  visible?: boolean,
  duration?: number,
  id?: string,
}

const props = withDefaults(defineProps<MessageProps>(), {
  tips: '',
  type: 'default',
  visible: false,
  duration: 3000,
  id: 'yzp-message'
})

const state = ref(false)
const title = ref(props.tips)
const status = ref(props.type)
const lock = ref(false)
const timer1 = ref(undefined)
const timer2 = ref(undefined)

watch(() => props.visible, (val: boolean) => {
  state.value = val
  show()
})

const hide = () =>{
    timer1.value = setTimeout(() => {
    lock.value = false
  }, props.duration - 300)

  timer2.value = setTimeout(() => {
    state.value = false
    document.body.removeChild(document.querySelector('#' + props.id))
  }, props.duration)
}

const show = () => {
  if (state.value) {
    return
  }
  
  clearTimeout(timer1.value)
  clearTimeout(timer2.value)

  state.value = true
  lock.value = true

  hide()
}

onMounted(() => show())

</script>

<template>
  <div v-if="state" :class="{ zoomOut: !lock }" class="yzp-message-wrap zoomIn">
    <div class="yzp-meesage-box blur">
      <span class="yzp-message-tip">{{ title }}</span>
      <img class="yzp-message-img" :src="`/img/message/${status}.png`" />
    </div>
  </div>
</template>

<style scoped lang="less">
.yzp-message-wrap {
  position: fixed;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  display: flex;
  justify-content: center;
  align-items: center;
  margin: auto;
  z-index: 999;
}
.yzp-message-wrap .yzp-meesage-box {
  box-shadow: 0 0 10px var(--border-1);
  border: 1px solid var(--border-1);
  padding: var(--space-15);
  display: flex;
  align-items: center;
  border-radius: var(--border-radius);
}
.yzp-message-wrap .yzp-message-img {
  width: 45px;
  height: 45px;
  margin-left: 15px;
}
.yzp-message-wrap .yzp-message-tip {
  font-size: 14px;
}
.zoomIn {
  animation: zoomIn 0.3s linear;
}
.zoomOut {
  animation: zoomOut 0.3s linear;
}
@keyframes zoomIn {
  0%,30% {
    opacity: 0;
    transform: scale(0.5);
  }
  100% {
    opacity: 1;
    transform: scale(1);
  }
}
@keyframes zoomOut {
  0% {
    opacity: 1;
    transform: scale(1);
  }
  100% {
    opacity: 0;
    transform: scale(0);
  }
}
</style>

plugins/message/index.ts代码

import Message from './index.vue'

interface MessageProps {
  tips?: string,
  type?: any,
  visible?: boolean,
  duration?: number,
}

// 插件注册
import { createVNode, render } from 'vue'

const Ele = function(props: MessageProps) {

  if (process.client) {
    const id = 'yzp-message'
    const div =  document.querySelector('#' + id)

    if (!props.visible) {
      return
    }

    if (div) {
      document.body.removeChild(div)
      return
    }

    const container = document.createElement('div')

    container.id = id

    const vm = createVNode(Message,  { id, ...props })

    render(vm, container)

    document.body.appendChild(container)
  }

}

export default {

  success(tips: string) {
    Ele({ type: 'success', visible: true, tips })
  },

  warning(tips: string) {
    Ele({ type: 'warning', visible: true, tips })
  },

  error(tips: string) {
    Ele({ type: 'error', visible: true, tips })
  }

}

 

plugins/index.ts代码

import message from './message'

export default defineNuxtPlugin((nuxtApp) => {
  return {
    provide: {
      message
    }
  }
})

 

在组件或者页面中使用

<script lang="ts" setup>
const { $message } = useNuxtApp()
$message.success('创建成功了')
</script>

 

支付宝微信
6
关注公众号获取更多内容
nuxt3配置多环境变量
结合lazyload实现文章页里面的图片预加载
共有 1 条评论
发表评论
  • hixb#10126
    2023-12-26 17:28
    广东省东莞市
    Windows 10
    Chrome

    这个版本好像有点老了

总共 1
  • 1
不支持canvas
春季
夏季
秋季
冬季
暗黑
简约
小清新