我们在开发一些组件插件的时候,需要动态的从外部去注入第三方插件
1. 如何做一个插件化的项目,模拟代码如下
// 插件设计内容
// 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
<template><div class=""><button>btn</button></div>
</template><script setup lang="ts">
</script><style scoped>
</style>
components/MyText.bue
<template><div class="">mytest</div>
</template><script setup lang="ts">
</script><style scoped>
</style>
- 制作插件底座
setup.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 = baseBlocksgetBlocksMap(){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
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
<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>