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>
这个版本好像有点老了