分类
js

Nervenet + Backbone

使用Backbone时,配合Nervenet能取得很好的效果。

介绍Nervenet起源时我提到,Nervenet一名很大程度上来自于Backbone。使用Backbone进行开发期间,我体会到很多方便之处,也发现仍有不少障碍横垣在前,于是总结之前的经验,取Robotlegs之长,做出了这个框架。当然,Nervenet并非专门针对Backbone开发,自然也不会依赖它,不过由于设计初衷和后期实现,结合Nervenet使用Backbone时着实有一些优势。

context.createInstance创建实例

我们知道,依赖注入的对象一般都是类的实例;类实例化时,可能会用到一些尚未注入的属性,所以通常需要在注入后调用实例的postConstruct方法,才能彻底完成构造。Backbone为了实现其独特的架构,将真正的构造函数construct隐藏了起来,开发者操作的initialize函数实际上是初始化函数,从执行顺序来讲与上文中的postConstruct基本一致。同时,Backbone的几大基础类都接受传入初始化对象,即new Backbone.View(options);中的optionsoptions中若包含elmodel等属性,将直接用来填充类自身的属性,甚至从页面当中找到dom结构操作。

若采用普通的依赖注入,则需要在每个类中再实现一个postConstruct方法,增加维护成本和迁移成本。使用Nervenet提供的context.createInstance方法,可以在实例化对象时,扫描参数对象,完成注入,只需要保留initialize函数,非常简单,而且可以直接沿用之前的代码。

var view = context.createIntance(Backbone.View, {
  model: '{{$model}}'
});

从代码可以看出,要完成上述功能,还必须实现一个特性:“注入指定类型的对象”。Javascript是弱类型语言,代码中不包含对象类型,所以之前的类库只能根据“属性名”注入。对于Backbone来说,modelcollection这些都是特有的关键字,要注入的也多是它们,而要注入model,就必须先map一个值到model这个key中——这意味着同一组map只能给单一Backbone.View对象注入依赖,在实际开发难以想象。Nervenet的优势在于可以由“属性值”指定注入的内容,这样不同的View,可以指定不同的model,问题迎刃而解。

// 给不同的view注入不同的model
context.createInstance(Backbone.View, {
  model: '{{$user-model}}'
});

context.createInstance(Backbone.View, {
  model: '{{$job-model}}'
});

infuse.js的解决方案是“子注入器”,通过创建子注入器,构造不同的map,就可以对不同对象注入不同的值了)

mediatorMap管理mediator

了解Backbone的人都知道,虽然名为View,但其实Backbone.View更接近一般意义上的Mediator,而通常意义上的View则由HTML+CSS负责实现。我通常使用Backbone.View开发组件,组件拼接起来就是完整功能的页面嘛。所以我就设计了一个功能来帮助我管理mediator,就是context.mediatorMap,它主要提供三个方法:

.map(selector, MediatorClass[, options]),通常和.check(dom)连用。前者将选择器和类关联,后者则检查某个DOM节点下是否有符合选择器的节点,并为它们自动创建mediator

// 先这么注册一下
context.mediatorMap.map('.checkbox', MyCheckbox, options);

// 然后就可以用了
context.mediatorMap.check(document.getElementById('my-form'));

.createMediator(dom, MediatorClass[, args]),直接为某DOM节点创建mediator

// 直接为DOM创建mediator
context.mediatorMap.createMediator(document.body, MyGUI);

创建mediator的过程基本相同,自动注入依赖,并把目标DOM节点会作为第一个参数,或者第一个参数对象的el属性传给mediator的构造函数——后者当然是为了兼容Backbone。

Backbone基于jQuery,所以操作一个DOM和操作一组DOM对它来说没有什么区别,留意到这点后,我在Nervenet中也作相应照顾,可以通过options设置isSingle=true;表示使用者希望使用一个实例来管理所有符合要求的节点。默认false,会针对每个DOM节点创建独立的mediator

可惜的是,HTML没有提供方便的手段获取DOM节点的变化,所以暂时只好使用手工检查了;另外,querySelectorAll这个方法也存在一定的兼容性问题,所以,目前mediatorMap仍然只是0.1.2版的测试功能,以后可能会有各种改动。

由meathill

爱编程,爱旅游,爱吐槽。
今年的目标是完成并运营至少一个 Side Project。
《Electron + Vue 实战开发》龟速创作中……

欢迎吐槽,请勿装死

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据