JS类库下插件/钩子设计思想

经常在使用各种js类库/框架中,往往他们都提供了各种插件机制,来新增补充各种功能,下面想分享一下最近学习各种框架,自己总结一下插件的实现和使用的方式

哪些情况下需要使用插件或者钩子

前端开发中,我们需要设计一个模块,或者一个小型的框架和库,但是前期的功能,比较少,实现是一个简单的版本,随着版本的迭代,我们需要实现的功能会越来越多,但是往往现在想推到代码重新编写,这样费时费力,如果前些实现功能时,预留插件机制或者钩子,那么在版本迭代的时候可以使用插件或者钩子来实现新功能,这样代码的复用性和维护性都往往提高不少

下面以开发一个图表组件来阐述我的思想

主逻辑

function plugins(Obj)
{
    this.plugins = {}
    this.plugins.Obj = Obj
}

plugins.extends = function(target){
    Object.keys(target).forEach(d => {
        pligins.prototype[d] = target[d]
    })
}

plugins.extends({
    addPlugin: function(hook, fn) {
        var me = this
        if (Object.keys(me.plugins).includes(hook)) {
            me.plugins[hook].push(fn)
        } else {
            me.plugins[hook] = fn
        }
    },
    removePlugin: function(hook, fn) {
        var me = this
        if (me.plugins[hook]) {
            var index = me.plugins[hook].indexOf(fn)
            me.plugins.splice(index, 1)
        }
    },
    notify (hook) {
        this.plugins[hook].forEach(d => {
            d.call(null, this.plugins.Obj) 
        })
    }
})
//  图表的实现
function Chart (ctx, config) 
{
    this.plugins = new plugins(this) // 插件的储存目录
    this.config(config)
    this.update(); // 数据更新和图表绘制
}

Chart.prototype.initialize =  function () {
    var me = this
   // 埋下插件的钩子
   me.plugins.notify('beforeInit')
  //  执行其他逻辑
   me.plugins.notify('afterInit')
   //  后置逻辑
 }

调用代码

var  chart =  new Chart(canvas,  config)

chart.plugins.addPlugin ('beforeInit', function(chart) {
  console.log('前置插件')
})
chart.plugins.addPlugin ('afterInit', function(chart) {
  console.log('后置插件')
})
chart.initialize() // 初始化

以上简单实现来一个简单的函数式插件,需要的逻辑都封装在一个插件函数中,当然这样的实现,可以在前置、后置补充很多逻辑,这种封装做的还不是够完美,其实可以把插件实现类似vue.use() 这样来安装,有一个契约规则,让插件编写的规范化

插件和钩子的思想

对于一个前端组件,其实我们在编写的时候也应该有各种生命周期的概念,这样我们可以更加合理的来组织我们的代码。
以图表组件为例说明。

生命周期图

对于这个组件,应该至少有三个阶段, 初始化, 数据变化, 组件析构

所以,我们需要做插件和钩子应该有两种思想。

  • 做钩子函数
    可以利用刚刚写的plugins插件实现在生命周期里的钩子函数,在三个阶段 或者 任何更新函数前,都可以埋点。

  • 做插件
    插件其实可以做的更加复杂
    我们可以提供类似这样的代码

var plugins = {
  data,
  afterinit() {},
  update() {},
  beforeinit() {}
}

来注册在生命周期中任何阶段都可以执行的逻辑。

  • 扩展类库的本上的方法

jQuery 通过 extend 来提供了 修改原型链上的方法和扩展明名空间上的静态方法

  • 拓展组件ui 库

现在流行的mvvm类库,其实都提供了 组件注册的方式来使用。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1、通过CocoaPods安装项目名称项目信息 AFNetworking网络请求组件 FMDB本地数据库组件 SD...
    阳明AI阅读 16,038评论 3 119
  • 我是在今年一月底的时候预知自己要毕业了的。我清楚地记得,年后大概是初十的那天,家里的哥哥姐姐和玩伴都已经全部离开我...
    醋溜愤青阅读 2,642评论 0 1
  • 常听人说女孩子要多出去旅行,才能扩大自己的视野。我这个人吧,严重的宅女,不爱玩,也不会玩。平日除了上班,下班,...
    回眸来时路阅读 4,306评论 0 1
  • 我们都希望家里的宠物健康、漂亮、可爱并且乖巧懂事。前者需要我们精心的照顾和打理,后者则需要我们通过科学合理的方法去...
    辰丶墨阅读 9,319评论 1 2
  • 1 人类需要证明自己活着。有时这种证明有多种方式,但在这之前,有一个重要的证明——一颗能跳动的心脏。 2 有时候在...
    桃之夭0310阅读 1,501评论 0 0