本文不讨论Backbone(一下简称BN)的优缺点,已经认为你在使用BN或者想使用BN。
这是我在项目中的使用经验拿出来和大家分享讨论:
(为了保密,以下的代码不是项目中的真是代码,单纯为了举例说明)
1. 项目组织结构。
前端使用的ROR,后端是纯RESTFul接口。
目录:
MyProject 根路径
public 公共资源路径
css 层叠样式表库
img 图片库
js JavaScript库
app.js 实例的初始化文件,项目入口文件
models.js 原型类库
views.js 视图类库
collections.js 集合类库
router.js 路由类库
common.js 公共JS库
views 视图实例库
system 系统管理模块
users.js 用户管理视图
roles.js 角色管理视图
chart 展示图管理模块
pies.js 饼图管理模块
template 模版库
system ...
users.html 用户管理使用模版
roles.html 角色管理使用模版
chart ...
pies.html 饼图展示模版
common.html 公共展示模版
上面仅展示了JSMVC相关的目录结构。蓝色为目录,绿色是文件。
其中视图的js和模版分别进行了模块化,创建了对应的目录结构(system和chart)
2. Backbone 本身没有模块化,这是我们不太爽,因为如果你对用用户和角色都有CRUD的操作,你为了避免命名冲突就要使用addUser、addRole、editUser、editRole...这当然不爽了,那么我们自己实现模块化。
对Model模块化:
// public/js/models.js
var company = (function(c){
c.model.system = (function(s){
s.User = Backbone.Model.extend();
s.Role = Backbone.Model.extend();
return s;
})(c.model.system || {})
return c;
})(company || {});
对Collection模块化:
// public/js/collections.js
var company = (function(c){
c.coll.system = (function(s){
s.Users = Backbone.Collection.extend({
url: '/users',
model: c.system.User
});
s.Roles = Backbone.Collection.extend({
url: '/roles',
model: c.system.Role
});
return s;
})(c.coll.system || {})
return c;
})(company || {});
对View类的模块化:
如果是列表视图一般不用创建多个,因为都是在页面的同一地方进行展示,所以使用统一的视图,然后覆盖其render方法即可。
对页面的模块化:
// public/js/views/system/users.js
var company = (function(c){
c.view.system = c.view.system || {}
c.view.system.user = {
list: function(){};
add: function(){};
edit: function(id){};
del: function(ids){};
};
return c;
})(company || {});
// public/js/views/system/roles.js
var company = (function(c){
c.view.system = c.view.system || {}
c.view.system.role = {
list: function(){};
add: function(){};
edit: function(id){};
del: function(ids){};
};
return c;
})(company || {});
对Router的模块化:
// public/js/router.js
var company = (function(c){
c.router = (function(r){
r.Base = Backbone.Router.extend({
routes: {
"system": "changeToSystem",
"chart": "changeToChart"
},
changeToSystem: function(){},
changeToChart: function(){}
});
r.base = new r.Base();
return r;
})(c.router || {})
var SystemRouterAndSystemView = (function(rs, vs){
rs.User = Backbone.Router.extend({
routes: {
"system/users": "index",
"system/users/add": "add",
"system/users/edit/:id": "edit",
"system/users/del/:ids": "del"
},
index: function(){
vs.user.list();
},
add: function(){
vs.user.add();
},
edit: function(id){
vs.user.edit(id);
},
del: function(ids){
vs.user.del(ids);
}
});
rs.Role = Backbone.Router.extend({
routes: {
"system/roles": "index",
"system/roles/add": "add",
"system/roles/edit/:id": "edit",
"system/roles/del/:ids": "del"
},
index: function(){
vs.role.list();
},
add: function(){
vs.role.add();
},
edit: function(id){
vs.role.edit(id);
},
del: function(ids){
vs.role.del(ids);
}
});
s.user = new s.User();
s.role = new s.Role();
return [rs, vs];
})(c.router.system || {}, c.view.system || {})
c.router.system = SystemRouterAndSystemView[0];
c.view.system = SystemRouterAndSystemView[1];
Backbone.history.start();
// route to first page
c.router.base.navigate('system', true);
return c;
})(company || {});
这样就完成的我们的项目的模块化改造,你已经看见在router中调用的是c.view.system.user.add()和c.view.system.role.add(),此function分别再两个js中,方法名都是add,这样我们的代码清爽多了,也不用在考虑命名冲突的问题了。
3. 谈一谈app.js的使用,我的app.js
var company = (function(c){
c.view.topMenu = new c.view.TopMenu().render();
c.view.secondMenu = new c.view.SecondMenu();
c.view.toolMenu = new c.view.ToolMenu();
c.view.mainTitleView = new c.view.MainTitle();
c.view.mainSearchView = new c.view.MainSearch();
c.view.mainOperationsView = new c.view.MainOperation();
c.view.mainContentView = new c.view.MainContent().render();
c.initMenusAndTools = function(currentTopMenu){
// overwrite view of secondMenu
c.view.secondMenusView.menus.reset();
_(currentTopMenu.children).each(function(menu){
c.view.secondMenusView.menus.add(new c.Menu(menu));
})
// overwrite view of toolMenu
c.view.toolMenu.collection.reset();
_(currentTopMenu.toolbar).each(function(menu){
c.view.toolMenu.collection.add(new c.model.Menu(menu));
})
}
return c;
})(company || {});
可以看得出来我对页面的基本框架的视图进行的默认的初始化,包括顶级菜单,二级菜单,工具栏,搜索栏,操作按钮集,重要内容显示区。这样只要修改相应的数据,对视图的部分进行修改就可以了。
initMenusAndTools是再模块切换(从system模块切换到chart模块)的时候初始化二级菜单和工具栏用的。
创建菜单的数据对象(JSON)。
// gloabal var for modularization
company = {}
company.model = {}
company.view = {}
company.coll = {}
company.router = {}
company.menus = [
{title: 'User', clazz: 'focus', action: '#user',
children: [
{title: '用户管理', clazz: 'user', action: '#system/users'},
{title: '角色管理', clazz: 'role', action: '#system/roles'}
],
toolbar: [
{title: '新建用户', clazz: 'newUser', action: 'javascript:void(0)'},
{title: '新建角色', clazz: 'newRole', action: 'javascript:void(0)'}
]
},
{title: 'Chart', clazz: '', action: '#chart'}
]
4. 再说一下项目中的公共组件。
// useage: new c.DisposableView({el: el, model: obj}).render('templateId');
c.DisposableView = Backbone.View.extend({
render: function(templateId, callback){
var template = _.template($('#' + templateId).html());
// The obj can be a native object or a instanceof Backbone.Model.
$(this.el).html(template({obj: _(this.model).nativeObj()}));
if(callback) callback();
return this;
}
})
这个一次性视图,根据指定的模版和对象来展现视图,为那些只适用一次的,仅仅用来展示的功能提供的。例如我们经常用的添加用户和添加角色等和业务相关的视图。
顺便说一下上面的nativeObj,这是我自定义的使用underscore的mixin整合的方法,目的就是将Backbone的model实例转换成js的本地对象,如果已经是本地对象则直接返回,代码如下:
_.mixin({nativeObj: nativeObj});
// if the object is Backbone.Model's instance and then change it to Native Object.
// if the object is Native and then return it.
function nativeObj(obj){
if(_(obj).isNull() || !_(obj).isObject()) return;
return (obj instanceof Backbone.Model) ? obj.toJSON() : obj;
}
5. 还有因为目前项目还没有使用requireJS,所有js的加载顺序要注意。
......
写了一大堆,更像是个人的总结,当然还没有结束,因为我也是刚开始用Backbone.js,以后还会进行更新。
分享到:
相关推荐
Backbone.js教程还包含了一些实际的案例,例如使用Twitter API进行无限滚动效果的实现,使用require.js模块化组织你的Backbone应用,以及如何使用Backbone.js、Node.js、Restify、MongoDB和Mongoose构建一个简单的...
虽然描述为空,但我们可以推断博主可能在博客中分享了他们首次尝试整合RestEasy和Backbone.js时的经验和学习过程。可能包括设置环境、创建REST服务、使用Backbone模型和视图与服务器通信、处理数据以及解决遇到的...
本文将深入探讨在Backbone View之间如何有效地传递值,同时也会分享一些在实际项目中遇到的问题及其解决方案。 首先,我们来看最常见的Backbone事件注册机制。这种机制允许我们将Backbone作为一个事件中心,使得...
3. 社区论坛或讨论区,俄语开发者可以在这里交流问题、分享经验,共同提升技术水平。 对于初学者,了解Backbone.js的基本结构和工作原理非常重要。开始时,学习如何定义模型、创建视图、使用集合和路由器是基础。...
商之狄以自身丰富的行业经验,从多个案例出发,分享了他在设计复杂多源系统集成时的实践心得。他强调了系统设计初期的重要性,以及建筑材料选择对于架构质量的影响。在混合架构中,他提到使用商业软件作为外围技术...
Thomas是Georgia Tech教育技术部门的前端开发专家,在书中将分享如何使用JavaScript、HTML和CSS来构建实用的数据可视化图形。对于已经熟悉网页制作但不完全清楚如何构建好的可视化的读者来说,这本书能够提供一个很...
mmdetection有一个活跃的社区,用户可以在GitHub上提交问题、分享经验,获取最新的开发动态和更新。此外,社区还提供了大量的示例代码和实战项目,帮助用户更好地理解和运用mmdetection。 总之,mmdetection是一个...
《21CN前端开发团队的发展历程与经验分享》 21CN前端开发团队,作为中国电信集团旗下子公司——世纪龙信息网络有限责任公司的核心部门,历经多年发展,已成为业界极具影响力的技术团队。自2010年成立以来,团队从...
在探讨“公共技术平滑落地的探索与实践”的过程中,史泓先生分享了他在税友集团体验技术团队的经验,深入探讨了公共技术落地过程中的挑战、理论和实践策略。史泓先生有着丰富的从业经历,专注前端领域长达七年之久,...
Deeplab v3 还阐述了训练细节并分享了训练经验。 Deeplab v3 将空洞卷积应用在了级联模块,并且改进了 ASPP 模块。backbone 仍然是 ResNet 101。增强 ASPP 模块,复制 ResNet 最后的 block 级联起来,加上 BN。...
4. **技能要求**:前端开发者应有扎实的HTML5/CSS3/JavaScript/Ajax基础,能手写代码,擅长使用jQuery、Backbone.js、AngularJS等JS框架,解决浏览器兼容性问题。熟练掌握Photoshop等设计软件,了解响应式网页开发、...
RouterOS 是一种强大的路由器操作系统,尤其在动态路由配置方面具有很高的灵活性。OSPF(开放最短路径优先)是一种内部网关...如果你对RouterOS的动态路由协议感兴趣,可以进一步研究相关资料,共同探讨和分享经验。
"特吕古尔"是一个基于Ruby on Rails和Backbone.js技术栈开发的项目,它旨在模仿流行的图片分享网站imgur的功能。这个项目是作者在App Academy的最终学习成果,展示了其在Web开发领域的技能和实践经验。 Ruby on ...
9. **社区与支持:**由于JointJS是开源项目,它拥有活跃的社区,开发者可以在社区中提问、分享经验,获取帮助和更新。 10. **与其他技术的集成:**JointJS可以轻松地与前端框架如React、Vue、Angular等集成,也可以...
- **Backbone.js**:轻量级框架,提供了基本的模型、集合、视图和路由器的概念,适合需要高度定制化的项目。 - **Batman.js**:强调高性能和简洁的API,采用虚拟DOM技术来提高渲染效率。 - **CanJS**:提供了一系列...
3. **促进知识分享**:鼓励团队成员分享自己的经验和知识,促进相互学习和成长。 4. **强化团队协作**:通过团队建设活动增强成员之间的信任和协作能力。 5. **实施敏捷开发**:采用敏捷开发方法可以快速响应变化,...
JavaScript拥有庞大的开发者社区,2014年的JSDC也可能是开发者交流经验、分享工具和最佳实践的平台。Gulp、Grunt等构建工具,以及Babel、ESLint等语法转换和代码质量检查工具,可能是讨论的重点。 综上所述,2014年...