一、创建目录
在components的Loading文件夹下建立 index.ts 和 index.vue两个文件。ts文件是一个 TypeScript 文件,通常用于编写逻辑、功能模块或导出一些工具函数、类、接口等。
二、编写插件内容
index.ts
/*
支持两种格式:
1、是对象形式: 对象形式必须包含一个install函数。他会回传一个app,这个app就是我们main.ts中的app
2、是函数形式
*/
import type {App,VNode} from 'vue'
import Loading from './index.vue' //引入自定义插件
import { createVNode,render } from 'vue' //将内容转化为vnode格式,方便阅读
export default{
install(app:App){
const Vnode:VNode = createVNode(Loading)
render(Vnode,document.body) //挂载,第一个是挂载的内容,第二个是挂载点(因为是全局的,我们挂载到document.body上)
//通过Vnode.component?.exposed 读取插件中的属性和方法
//设置为全局变量
app.config.globalProperties.$loading={
show: Vnode.component?.exposed?.show,
hide: Vnode.component?.exposed?.hide,
}
//调用,下面操作会在每个页面上都显示show().
//app.config.globalProperties.$loading.show()
//console.log(app,123,Vnode.component?.exposed)
}
}
index.vue
<template>
<div v-if="isShow" class="loading">
Loading...
</div>
</template>
<script setup lang='ts'>
import { ref,reactive } from 'vue'
const isShow = ref<boolean>(false)
const show = () => isShow.value = true
const hide = () => isShow.value = false
//函数和方法都必须放在defineExpose,否则挂载的时候无法读取到。
defineExpose({
show,
hide,
isShow
})
</script>
<style scoped>
.loading{
background: black;
opacity: 0.8;
font-size: 30px;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
color: white;
}
</style>
三、在main.ts文件中引入和注册
//import './assets/main.css'
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
import router from './router'
/*
1、导入插件
./components/Loading
优先引入index.ts,如果没有index.ts,那么就会自动寻找index.vue
同时存在 index.ts 和 index.vue,则通常会优先解析 index.ts,除非项目配置中有特殊的解析规则。
*/
import Loading from './components/Loading'
const app = createApp(App)
//2、注册插件。只要是vue的插件,都必须通过这个方法注册
app.use(Loading)
app.use(createPinia())
app.use(router)
app.mount('#app')
四、使用
在要使用的页面先获取实例
<template>
<div>我是主页面</div>
</template>
<script setup lang='ts'>
import { ref,reactive,getCurrentInstance } from 'vue'
//获取实例
const instance = getCurrentInstance()
//获取实例中自定义插件(可以正常使用,但是报错,可以在main.ts中做类型声明。)
instance?.proxy?.$loading.show()
setTimeout(()=>{
instance?.proxy?.$loading.hide() //5秒钟之后关闭
},5000)
</script>
<style scoped>
</style>
在main.ts中 做类型声明,阻止报错。
//import './assets/main.css'
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
import router from './router'
import Loading from './components/Loading'
const app = createApp(App)
app.use(Loading)
//做类型声明
/*
在 Vue 3 中,如果你只是想对组件实例或全局属性进行扩展,
建议使用 declare module '@vue/runtime-core',因为它更符合 Vue 3 的内部结构。
如果没有安装会报错,可以使用pnpm install @vue/runtime-core @types/node。进行安装。
如果你需要扩展 Vue 整体的公共 API(如 Vue 全局属性),
可以使用 declare module 'vue'。
有时候,二者可以随便选择使用。
*/
type Lod ={
show: () => void,
hide: () => void
}
declare module '@vue/runtime-core'{
export interface ComponetCustomProperties {
$loading:Lod
}
}
app.use(createPinia())
app.use(router)
app.mount('#app')