Backbone Conf 2012
有幸去美国波士顿参加了2012年的 Backbone.js Conference,见到了coffeescript、underscore.js 还有 backbone.js 的作者 Jeremy Ashkenas。会议内容围绕前端MVWTF和社区进行了很多有趣的讨论,有很多有价值的观点。我希望在这里面与大家分享我从里面学到的东西。
这系列博客其实是我整理的会议笔记的汇总,是我对每个话题中比较有印象或者比较重要的内容的摘抄,这些观点几乎都不是我的,我仅作为一个传声者。我是希望把所有的Credit交给演讲者自己,我最多只是一个翻译者,碰巧幸运的在现场。Backbone.js Conference和O’Reilly的Fluent Conference 碰巧同时进行,#BackboneConf 更加草根,但是也更有观点。
Keynote for BackboneConf by Jeremy Ashkenas
Links
Notes
- Backbone.js成长的非常快,只用了1.5年就在社区内引起了巨大的反响
- Backbone是来自真实的项目,满足真实的需求,这个框架只是一个副产品
- Backbone.js是抽出DocumentCloud项目可复用的部分的产物
- Backbone.js的用户很大牌
Backbone.js是一个small、simple、flexible的框架,所以没有典型的Backbone应用,我们现在看到的例子只是冰山的一角。
传统的JQuery的一个大的问题就是它面对的是获取文本,更新HTML上的另外一些文本。但是这个过程中我们没有明确的获取和渲染数据模型。
Avoid jQuery hell by getting your state of out of the DOM
因为JQuery更新的Dom本身就是有状态的,所以代码尝尝混杂者状态判断的逻辑,这是很让人头疼的状态。
Model is where your data lives, source of truth for application. UI only knows about the truth in the models. UI can’t conflict with others
数据模型应该表示状态,让UI与状态分离,这样UI之间就不会因为复杂的状态而纠缠不清。
在Backbone.js里面,我们修改Model的状态。而其它的组件监听Model的事件。
ClientSide的collection一般是整体Model的repository的一个子集。Model是个体,而collection是集合。他们是保持客户端状态的基础。Underscore.js用来访问Model和Collection,它是Backbone.js的魅力的体现。
Ashkenas演示了他们使用namespace,把系统中所有的Model和View实例全部都放在一个树型数据结构上,可以看到View的实例一般是绑定在相应的Collection和Model下面。这个树形数据结构保存了客户端的所有状态和实例,对于debug非常有利。View放在Collection和Model下面是因为View是无状态的(它依附于相应的Collection和Model的状态)。
Changes
一般的模式是Model被set后View就re-render,View会监听change事件。Model和Collection的save的语义是将变化传递到服务器(持久化),而set只是修改状态并触发change。
Model和Collection初始化的时候可能需要逐层载入,这个时候可能会触发多次change,可以使用参数{silent: true}。它是专门应对触发change的中间状态而设计的,当需要触发View的re-render时再trigger change事件。这样的设计可以保证View是完全无状态的。
有人问客户端Model会有一些对服务器端没有意义的属性,如selected表示一个模型是否是被选中的状态,这可以么?
因为Model是用来保存系统状态的,所以这些状态属性就应该放在Model里面。
View的更新是应该使用乐观模式还是悲观模式呢?(是否等待状态保存到服务器后再更新UI)。
这个要看场景,Instagram就做了很多这样的trick。避免状态不一致是最重要的,所以对于不太可靠的更新需要使用悲观方式。
Model之间的关系如何传递?Model的属性是否可以是collection。
可以,通过Model和它的属性间的event proxy传递event。(第二天的SuperModel,还有其它解决方案,可以用声明的方式绑定Model和sub models之间的关系,自动proxy event)
change event的listener可以通过this.get(‘prop’)和this.previous(‘prop’)来获取修改的属性的变化情况。
Views
Views should be stateless!!!
- View is stateless if it always has a dom element at all times
- Did my view render in a particular mode when it doesn’t exist? No, elem is always there and events are always delegated
View在它被初始化的时候它的element就应该已经存在,这样它的render和re-render就不会依赖于其它先置条件,从而保持stateless。
Backbone.js的哲学Philosophy
Take the truth out of the DOM.
- So the only truth is the model 😀
Intentionally minimal
- Small, Simple, Flexible
Resited Router for a while. Jeremy still thinks Router may be overreaching
Tries to be driven by use cases, not gospel. If you open ticket on GitHub without use cases, you’ll get ignored
Is Backbone.js MVC, MV+, MVP?
- It’s MVWhatever
- Important thing is that UI and Models are the common denominator. Build interesting UI without breaking app and build interesting business logic without breaking UI.
- 最重要的分离是Model和View的分离,Model是保持状态的核心,View是无状态的
Statelessness
- Backbone doesn’t do it for you
- Exponential states of UI should be avoided. Don’t enumerate every state
- UI因为是一种组合视图,所以它的状态是指数式增长的,所以要避免枚举UI的状态组合,保证UI是无状态的
- Models contain state, UI listens to models, but UI doesn’t care about what is going on with rest of app
Other things discussed in this session
- 在客户端和服务器端共享代码?Jeremy觉得这好像不是个好主意,但是在服务器和客户端建立一种Event传递机制似乎是一个可以考虑的方向。
- 大家公认View的unload是一个痛点:大家发现View的初始化往往比较容易,但是View在不活跃或者需要被替换掉的时候如何unbind事件,如何处理已经渲染过的Dom,解除所有其它的双向依赖是个问题。因为View和子View的生命周期和他们的依赖关系目前还没有被建模,所以没有统一的解决方法。Jeremy透露目前他们的解决方法是通过namespace下面的遍历来unbind所有的sub-view,这种方法在不是非常复杂的情况下是可行的。不过由于这个公认痛点的存在,社区内大家都在尝试找到一种比较通用的简单解决方法。