Backbone View 之间通信的三种方式


Posted in Javascript onAugust 09, 2016

在上篇文章给大家介绍了Backbone中View之间传值的学习心得。本文重点给大家介绍Backbone View 之间通信的三种方式。

掌握一个 MVC 框架,最关键的一节就是掌握如何在各个 View 之间通信。之前用 Angular 时,觉得基于事件的通信方式 ($on, $emit, $boardcast) 或者 基于 service 的方式都非常好用。转战 Backbone 之后,由于对 Backbone 的事件机制理解不够且使用非常灵活,一直没找到一个好的通信方式。直到看见这篇文章,作者通过一个简单的例子,层层深入,把 Backbone View 之间通信的三种方式讲的清晰明了。译文如下:

我正在开发的这个网页主要有两部分,分别是 document 和 sidebar。

Backbone View 之间通信的三种方式 

如上图所示,我设立了三个视图 (view) :

Backbone View 之间通信的三种方式 

ApplicationView - 作为最外层视图来包含下级视图

DocumentView - 展示正在编辑或浏览的内容

SidebarView - 展示一些和 document 相关的信息

DocumentView 和 SidebarView 作为 ApplicationView 的子视图,所以整体的视图结构如下图所示:

用户在任意一个子视图进行操作,另一个子视图都需要随之变化。但由于两个子视图之间并不能直接通知对方(也就是说,它们的作用域没有直接联系,不像父视图,可以包含它所有子视图的作用域),所以,我需要一个事件机制。

在我谷歌和参考其他人的方法之后,我总结出了如下三种不同的通信方式。

1. 通过父视图传递事件

我通过父视图 ( ApplicationView ) 来为它的两个子视图传递事件。因为父视图包含它所有子视图的作用域,因此用它作为事件传递的媒介最好不过。

Backbone View 之间通信的三种方式 

JavaScript 代码如下:

var ApplicationView = Backbone.View.extend({
initialize : function(){
this.documentView = new DocumentView({parent:this});
this.sidebarView = new SidebarView({parent:this});
this.documentView.on('edit', this.documentEdited, this);
},
documentEdited : function(){
// do some stuff
this.sidebarView.trigger('documentEdit');
}
});
var DocumentView = Backbone.View.extend({
onEdit : function(){
this.trigger('edit');
}
});
var SidebarView = Backbone.View.extend({
initialize : function(){
this.on('documentEdit', this.onDocumentEdit, this);
},
onDocumentEdit : function(){
// react to document edit.
}
});

但是,这种方法并不高效。因为我需要在 ApplicationView 中添加一个额外的事件处理函数 documentEdited() 。如果子视图有一堆事件传过来,则在父视图中会不断触发事件处理函数,导致它不堪重负。

那么来看看第二种方法。

2. 通过 EventBus 在视图间通信

我通过继承 Backbone.Events 来创建一个全局对象 EventBus 。把它注入到各个子视图中,用来广播事件。

Backbone View 之间通信的三种方式 

JavaScript 代码如下:

var ApplicationView = Backbone.View.extend({
initialize : function(){
this.eventBus = _.extend({}, Backbone.Events);
this.documentView = new DocumentView({
eventBus : this.eventBus
});
this.sidebarView = new SidebarView({
eventBus : this.eventBus
});
},
});
var DocumentView = Backbone.View.extend({
initialize : function(options){
this.eventBus = options.eventBus;
},
onEdit : function(){
this.eventBus.trigger('documentEdit');
}
});
var SidebarView = Backbone.View.extend({
initialize : function(options){
this.eventBus = options.eventBus;
this.eventBus.on('documentEdit', this.onDocumentEdit, this);
},
onDocumentEdit : function(){
// react to document edit.
}
});

在这个方法中,我把 EventBus 作为一个全局对象用来注册事件。如果我想在各个视图之间通信,只需要在视图中注入 EventBus ,就可以通过它方便地触发或监听事件了。

注意:如果你不想要创建全局对象,你仍然可以创建模块 (module) 或视图 (view) 级别的 EventBus 用来通信。

这个方法已经明显优于第一种方法了。但是需要我们手动的在子视图中引入 EventBus ,说明还有可以改进的空间,那么,来看看第三种方法。

3. 直接用 Backbone 作为事件注册机

在第二种方法中,我创建了一个单独的 EventBus ,继承自 Backbone.Events 。但最近我悟到 Backbone 对象本身就是一个混合了 Events 的对象,所以我直接用 Backbone 广播事件,就无需单另创建的 EventBus 了。

而且 Backbone 对象可以直接调用,这样我就不必在每个子视图中手动注入它了。

Backbone View 之间通信的三种方式 

JavaScript 代码如下:

var ApplicationView = Backbone.View.extend({
initialize : function(){
this.documentView = new DocumentView();
this.sidebarView = new SidebarView();
},
});
var DocumentView = Backbone.View.extend({
onEdit : function(){
Backbone.trigger('documentEdit');
}
});
var SidebarView = Backbone.View.extend({
initialize : function(options){
Backbone.on('documentEdit', this.onDocumentEdit, this);
},
onDocumentEdit : function(){
// react to document edit.
}
});

总结

我最终在我的项目中使用了第三种方法。而且在我看来,虽然它直接依赖了全局的 Backbone 对象,但是用起来却异常简洁。

Javascript 相关文章推荐
js电信网通双线自动选择技巧
Nov 18 Javascript
JavaScript截取字符串的2个函数介绍
Aug 27 Javascript
JavaScript tab选项卡插件实例代码
Feb 23 Javascript
jQuery Mobile漏洞会有跨站脚本攻击风险
Feb 12 Javascript
Node.js连接mongodb实例代码
Jun 06 Javascript
详解vue中computed 和 watch的异同
Jun 30 Javascript
JS解决position:sticky的兼容性问题的方法
Oct 17 Javascript
vue源码入口文件分析(推荐)
Jan 30 Javascript
JavaScript数组去重算法实例小结
May 07 Javascript
使用angularjs.foreach时return的问题解决
Sep 30 Javascript
2019 年编写现代 JavaScript 代码的5个小技巧(小结)
Jan 15 Javascript
VUE兄弟组件传值操作实例分析
Oct 26 Javascript
Backbone中View之间传值的学习心得
Aug 09 #Javascript
全面了解函数声明与函数表达式、变量提升
Aug 09 #Javascript
jQuery 生成svg矢量二维码
Aug 09 #Javascript
浅谈JavaScript中变量和函数声明的提升
Aug 09 #Javascript
浅谈js基本数据类型和typeof
Aug 09 #Javascript
js中判断变量类型函数typeof的用法总结
Aug 09 #Javascript
详解js实现线段交点的三种算法
Aug 09 #Javascript
You might like
PHP实现的微信公众号扫码模拟登录功能示例
2019/05/30 PHP
PHP基于session.upload_progress 实现文件上传进度显示功能详解
2019/08/09 PHP
laravel 错误处理,接口错误返回json代码
2019/10/25 PHP
二级域名或跨域共享Cookies的实现方法
2008/08/07 Javascript
boxy基于jquery的弹出层对话框插件扩展应用 弹出层选择器
2010/11/21 Javascript
仿新浪微博登陆邮箱提示效果的js代码
2013/08/02 Javascript
Javascript毫秒数用法实例
2015/02/05 Javascript
Javascript Function.prototype.bind详细分析
2016/12/29 Javascript
js记录点击某个按钮的次数-刷新次数为初始状态的实例
2017/02/15 Javascript
axios进阶实践之利用最优雅的方式写ajax请求
2017/12/20 Javascript
基于Vue实现拖拽效果
2018/04/27 Javascript
Node.js中的cluster模块深入解读
2018/06/11 Javascript
在Vue中获取组件声明时的name属性方法
2018/09/12 Javascript
javascript中关于类型判断的一些疑惑小结
2018/10/14 Javascript
浅谈VueJS SSR 后端绘制内存泄漏的相关解决经验
2018/12/20 Javascript
浅谈JavaScript面向对象--继承
2019/03/20 Javascript
小程序云函数调用API接口的方法
2019/05/17 Javascript
vuex存储复杂参数(如对象数组等)刷新数据丢失的解决方法
2019/11/05 Javascript
[02:27]DOTA2英雄基础教程 莱恩
2014/01/17 DOTA
[02:36]DOTA2上海特锦赛 回忆电竞生涯的重要瞬间
2016/03/25 DOTA
Python中unittest用法实例
2014/09/25 Python
python嵌套函数使用外部函数变量的方法(Python2和Python3)
2016/01/31 Python
浅谈Python小波分析库Pywavelets的一点使用心得
2019/07/09 Python
python模块hashlib(加密服务)知识点讲解
2019/11/25 Python
Python3中对json格式数据的分析处理
2021/01/28 Python
HTML5 解决苹果手机不能自动播放音乐问题
2017/12/27 HTML / CSS
Notino瑞典:购买香水和美容产品
2019/07/26 全球购物
捷克家电和家具购物网站:OKAY.cz
2020/07/23 全球购物
触发器(trigger)的功能都有哪些?写出一个触发器的例子
2012/09/17 面试题
企业宣传工作方案
2014/06/02 职场文书
计算机求职信
2014/07/02 职场文书
员工团队活动方案
2014/08/28 职场文书
研修心得体会
2014/09/04 职场文书
监察局领导班子四风问题整改措施思想汇报
2014/10/05 职场文书
2015感人爱情寄语
2015/02/26 职场文书
电影地道战观后感
2015/06/04 职场文书