vue3插件的编写
- 为什么要使用插件?
插件在Vue.js中是一种非常重要的功能扩展方式。使用插件可以帮助我们增加Vue.js的功能,或者改变Vue.js的行为。例如,Vue Router
和Vuex
就是Vue.js的官方插件,它们分别为Vue.js添加了路由和状态管理的功能。此外,还有许多第三方插件可以帮助我们解决各种特定的问题,如表单验证、日期处理等。使用插件可以让我们更好地复用代码,避免重复造轮子,提高开发效率。
- 插件与组件的区别?
组件是Vue.js中用于构建用户界面的可复用实例,它是Vue.js的基础。每个组件都是一个独立的视图模块,有自己的模板、数据、方法等。组件可以嵌套使用,通过组件的组合和嵌套,可以构建出复杂的用户界面。
插件则是用来扩展Vue.js的功能。一个插件可以添加全局方法或属性、添加全局资源、混入全局/局部的选项、添加Vue实例方法,或者提供自己的模块。
插件的目的是为了增加全局级别的功能,而组件则是为了封装和复用代码,构建用户界面。
编写并使用插件
- 先编写一个loding的组件,代码如下:
vue
<template>
<div v-if="show" class="loading">
<p>Loading...</p>
</div>
</template>
<script setup lang='ts'>
import { ref } from 'vue'
let show = ref<boolean>(false)
const isShow = () => {
show.value =true
}
// 将isShow方法暴露出去,使得插件可以获取到这个方法
defineExpose({
isShow
})
</script>
- 编写插件代码:
ts
import loading from './index.vue'
import { createVNode, type App,type VNode, render } from 'vue'
// loading插件 通过将loading文件夹下的index.vue挂载到全局,然后其余组件就可以直接使用
export default{
install(app:App){
// 要将loading转换为虚拟节点才能获取到需要的属性
const Vnode:VNode=createVNode(loading)
// 将虚拟节点挂载到全局body
render(Vnode,document.body)
// console.log(Vnode)
// 访问全局属性,由于vue官方不给使用setupState,所以需要组件将方法暴露出来给全局使用
app.config.globalProperties.$loadings={
isShow:Vnode.component?.exposed?.isShow,
}
// console.log(Vnode.component?.exposed)
}
}
- 在main.ts注册插件以及声明文件:
ts
import loading from './components/vue插件编写/loading'
export const app = createApp(App)
type Loadings = {
isShow: () => void
}
// 声明要扩充@vue/runtime-core包的声明.
// 这里扩充"ComponentCustomProperties"接口, 因为他是vue3中实例的属性的类型.
declare module 'vue' {
export interface ComponentCustomProperties {
$loadings: Loadings
}
}
// 注册插件loading
app.use(loading)
app.mount('#app')
- 使用插件:
vue
<script setup lang='ts'>
import { ref,getCurrentInstance } from 'vue'
// 获取当前组件的实例
const instance=getCurrentInstance()
instance?.proxy?.$loadings.isShow()
setTimeout(()=>{
instance?.proxy?.$loadings.isShow()
},2000)
</script>
源码解读
ts
const installedPlugins = new Set()
...
use(plugin: Plugin, ...options: any[]) {
// 判断是否已经注册过该插件
if (installedPlugins.has(plugin)) {
// 已经注册过就返回一个警告
__DEV__ && warn(`Plugin has already been applied to target app.`)
} else if (plugin && isFunction(plugin.install)) {
// 编写插件会实现install函数,在这里进行判断是否为函数
// 是函数就添加进set中进行缓存,然后调用这个函数将插件注册进app中,以及一些配置属性options
installedPlugins.add(plugin)
plugin.install(app, ...options)
} else if (isFunction(plugin)) {
// 判断plugin是否为函数模式
installedPlugins.add(plugin)
plugin(app, ...options)
} else if (__DEV__) {
warn(
`A plugin must either be a function or an object with an "install" ` +
`function.`
)
}
// 返回一个app,则可以进行链式的添加插件,例如:app.use(store).use(router).use(ElementUi)
return app
},