组件化开发优势
从2015以来前后端分离的模式被越来越多的公司所使用,随着业务代码复杂度的上升,代码也维护成本也随之上升。对于一个复杂的web应用,我们可以使用分而治之的方式来降低系统的复杂度,也就是标题中所说的组件化开发。组件化开发可以把系统分割多个子模块,每个模块完成单一的功能,不同模块可以相互组合、相互通信,从而构建大型复杂应用。
Backbone中的组件化和其他流行的前端框架相比并不是很完善,例如在Vuejs中我们只需要引入一个vue单文件组件就可以获得组件的Dom、样式、功能等。尽管Backbone没有官方推荐的组件化方案,但是我们可以使用webpack打包技术,以及自己对Backbone对象进行封装来实现类似于vue框架的组件化开发。
在下面的文章中我们一起,一步一步实现Backbone的组件化。
Backbone的组件化
Backbone是一个经典的MVC框架,但是本身并没有提供很完善的组件机制。我在开发的过程中碰到以下三个问题。
1. 模块中的各部分过于分散,无法集中应用
在Backbone中如果需要一个模块的渲染和事件绑定,我们至少需要在页面上调用model
和view
两个类。如果这个组件需要使用一组model那就需要调用Collection
类。这已经涉及到三个对象的调用。
如果模块中字符串模板的和css的引用,那么一个功能模块就涉及到5个资源的应用。而且资源分散在html文件、css文件、js文件中,这对于代码的模块化是极其不友好的。
2. 编译模板的效率
Backbone通常使用字符串模板来实现Dom结构,在官方提供的实例程序中,模板的编译是在View对象的初始化过程中完成的。也就是说模板编译是在浏览器首次加载View对象时完成的。代码贴上。
var AppView = Backbone.View.extend({
// Our template for the line of statistics at the bottom of the app.
statsTemplate: _.template($('#stats-template').html())
})
这会导致两个问题,第一浏览器编译模板文件是需要时间的,这部分工作完全可以在代码打包时候完成。第二、所有的模板需要在页面渲染之前完成编译,如果模板数量大的话会影响首屏性能。
3. 没有提供方便的模板嵌套组合的方案
如果要在backbone中实现组件嵌套(例如tab切换组件中嵌套多个自定义表单组件),那个tab组件的view和表单组件的view将耦合在一起。那个tab组件就失去了组件化的意义。来看看官方的例子。
var AppView = Backbone.View.extend({
render: function() {
// 这里的Todos Model是子模板的Model,也就是AppView和子模版的model耦合
var done = Todos.done().length;
var remaining = Todos.remaining().length;
// 无关代码。。。
},
addOne: function(todo) {
// 这里的TodoView是子模板的View,也就是AppView和子模版的View耦合
var view = new TodoView({model: todo});
this.$("#todo-list").append(view.render().el);
},
});
如何优化?
首先来定义我们做优化的目标。
- 首先希望做到组件的引用尽量简化、集中。最好和Vue的单文件组件类似。希望最终可以做到通过导入一个js文件就可以导入组件的Dom模板、样式、事件。这个改进可以通过webpack等打包工具完成,具体配置会在下一篇文章中展开。
- 接下来我们需要解决模板编译效率的问题。通过使用underscore-template-loader加载模板文件,我们在代码打包阶段完成模板的编译,具体配置会在下一篇文章中展开。
- 最后是要解决组件嵌套的问题。我们可以在Model和View对象的上层提供一个封装对象,并对外提供的接口。这样不同的组件可以通过统一的接口嵌套成复杂的组件。具体配置会在下一篇文章中展开。