前言
插件化机制在前端应用或者框架中的应用非常广泛。不论是业务开发还是框架开发,我们都能见到插件化设计。比如 webpack 基于 tappable 实现的插件化。
插件机制引入
class Calculator {
constructor (initial) {
this.num = initial
}
add(num) {
this.num = this.num + num
return this
}
subtract(num) {
this.num = this.num -num
return this
}
result () {
return this.num
}
}
const myCalculator = new Calculator(5);
let result = myCalculator.add(5).subtract(6).result();
console.log("🚀 ~ result:", result)
以上这个例子,我们定义了一个计算器,计算器有加减功能,但是如果我们希望增加乘除功能呢?没办法只能在类中修改代码,这是非常不灵活的,那我们可以怎么做?
- 构造计算机底座
- 计算机功能通过插件实现
插件化机制最重要的事是什么?没错就是插件底座,我们要开发计算器,我们只关心计算器整个底座,至于计算器有什么计算功能,交给外部,外部灵活拓展。顺着这个思路,那么计算器的各种计算方法就是插件,我们需要某个计算功能的时候只需要往插件系统中注册对应插件即可。
class Calculator {
constructor (initial) {
this.plugins = []
this.num = initial
}
use (plugin) {
this.plugins.push(plugin);
this[plugin.name] = plugin.calculate.bind(this);
}
result () {
return this.num
}
}
// 插件声明
interface Plugin {
name: string
calculate (num: number) => this;
}
// 插件实现
class AddPlugin interface Plugin{
name = 'add'
calculate(num){
this.num = this.num + num
return this
}
}
class SubtractPlugin interface Plugin {
name = 'subtract'
calculate(num) {
this.num = this.num - num;
return this
}
}
const myCalculator = new Calculator(5);
myCalculator.use(new AddPlugin)
myCalculator.use(new SubtractPlugin)
const result = myCalculator.add(5).subtract(8).result();
console.log("🚀 ~ result:", result)
这样改造之后,如果未来要实现乘法,我们只需新增一个插件实现既可,无需修改程序的主体:
class MultiplicatiPlugin interface Plugin {
name: 'multiplicati',
calculate(num) {
this.num = this.num * num;
return this;
}
}
通过上面的例子,从插件的角度可以分成几个部分:
- 程序主题(program),我们通常称之为插件底座,即上例的 Calculator;
- 插件接口声明(Plugin interface),即上列的 Plugin;
- 插件实现(Plugin Implementation),即 AddPlugin, SubtractPlugin...
总结
插件化机制应用非常广泛:
- 表单校验,校验规则就可以是插件化的,rules: [ { required: true }, { max: 20 } ]
- webpack、vue、pinia 这些框架,它的拓展能力都是通过插件化实现的