我们在开发一些组件插件的时候,需要动态的从外部去注入第三方插件
1. 如何做一个插件化的项目,模拟代码如下
ts
// 插件设计内容
// 1. 插件底座
// 2. 插件注册方式
// 3. 调用插件
class Calculator{
// 插件底座
plugins = []
constructor(){
}
// 注册
use(plugin){
this.plugins.push(plugin)
this[plugin.name] = plugin.fn
}
}
// 设置两个插件
const AddPlugin = {
name : 'add',
fn: function (a, b){
return a + b
}
}
class MinusPlugin{
name = 'minus';
fn(a, b) {
return a- b
}
}
const caculator = new Calculator()
// 把插件应用到组件中
caculator.use(AddPlugin)
caculator.use(new MinusPlugin())
// 使用插件
console.log(caculator.add(1, 2))
console.log(caculator.minus(2, 1))
console.log(caculator['add'](2, 1))
2. 有了以上的认识,我们开始制作插件
- 准备两个vue组件, 用于渲染的插件
components/MyButton.vue
ts
<template>
<div class="">
<button>btn</button>
</div>
</template>
<script setup lang="ts">
</script>
<style scoped>
</style>
components/MyText.bue
ts
<template>
<div class="">mytest</div>
</template>
<script setup lang="ts">
</script>
<style scoped>
</style>
- 制作插件底座
setup.ts
ts
import type { App } from 'vue'
import MyButton from './components/MyButton.vue'
interface BlockType{
type: string,
meterial: any,
}
// 先定义好自己已有的组件,添加进去
const baseBlocks = [
{
type: 'mybutton',
meterial: MyButton
}
]
class BlockSuite {
public blocks = baseBlocks
getBlocksMap(){
return Object.fromEntries(this.blocks.map((block) => [block.type, block]))
}
getBlocks(){
return this.blocks
}
// 可以添加第三方插件
addBlock(block: any){
this.blocks.push(block)
}
hasBlock(type: string){
return !!this.getBlocksMap()[type]
}
}
const blockSuite = new BlockSuite()
export const setup = (list: BlockType[], app: App<Element>) => {
list.map((block) => {
blockSuite.addBlock(block)
})
const blocksMap = blockSuite.getBlocksMap()
const ins = {
install(app: App<Element>) {
app.config.globalProperties.$blocksMap = blocksMap
}
}
app.use(ins)
}
- main.js 里面调用setup
ts
import { createApp } from 'vue'
import App from './App.vue'
import { setup } from './setup'
// 第三方插件
import MyText from './components/MyText.vue'
const app = createApp(App)
// 插入第三方库
setup([{type: 'mytext',meterial: MyText}],app)
app.mount('#app')
- 最后,我们可以在组件里面使用插件
App.vue
ts
<script setup lang="ts">
import { getCurrentInstance } from 'vue';
const {proxy}: any = getCurrentInstance()
const blocksMap = proxy.$blocksMap
</script>
<template>
<div>
<component :is="blocksMap['mybutton'].meterial"></component>
<component :is="blocksMap['mytext'].meterial"></component>
</div>
</template>
<style scoped>
</style>