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 相关文章推荐
web前端开发也需要日志
Dec 09 Javascript
THREE.JS入门教程(4)创建粒子系统
Jan 24 Javascript
jQuery使用append在html元素后同时添加多项内容的方法
Mar 26 Javascript
JavaScript资源预加载组件和滑屏组件的使用推荐
Mar 10 Javascript
在Vue中如何使用Cookie操作实例
Jul 27 Javascript
深入研究jQuery图片懒加载 lazyload.js使用方法
Aug 16 jQuery
javascript+jQuery实现360开机时间显示效果
Nov 03 jQuery
浅析Vue中method与computed的区别
Mar 06 Javascript
vue中typescript装饰器的使用方法超实用教程
Jun 17 Javascript
layui实现数据分页功能(ajax异步)
Jul 27 Javascript
Node.js API详解之 console模块用法详解
May 12 Javascript
详解JavaScript原型与原型链
Nov 16 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 MemCached 高级缓存应用代码
2010/08/05 PHP
zend optimizer在wamp的基础上安装图文教程
2013/10/26 PHP
关于扩展 Laravel 默认 Session 中间件导致的 Session 写入失效问题分析
2016/01/08 PHP
Win7环境下Apache连接MySQL提示连接已重置的解决办法
2017/05/09 PHP
Javascript 面向对象 继承
2010/05/13 Javascript
精通Javascript系列之数值计算
2011/06/07 Javascript
你必须知道的JavaScript 中字符串连接的性能的一些问题
2013/05/07 Javascript
YUI模块开发原理详解
2013/11/18 Javascript
JS+DIV实现鼠标划过切换层效果的方法
2015/05/25 Javascript
js实现文本框输入文字个数限制代码
2015/12/25 Javascript
AngularJs中route的使用方法和配置
2016/02/04 Javascript
使用Curl命令查看请求响应时间方法
2016/11/04 Javascript
JavaScript中EventLoop介绍
2018/01/22 Javascript
JS 实现获取验证码 倒计时功能
2018/10/29 Javascript
关于vue状态过渡transition不起作用的原因解决
2019/04/09 Javascript
vue自动路由-单页面项目(非build时构建)
2019/04/30 Javascript
关于ckeditor在bootstrap中modal中弹框无法输入的解决方法
2019/09/11 Javascript
vue 实现路由跳转时更改页面title
2019/11/05 Javascript
VUE项目实现主题切换的多种方法
2020/11/26 Vue.js
python字典键值对的添加和遍历方法
2016/09/11 Python
python 实现一个贴吧图片爬虫的示例
2017/10/12 Python
matplotlib简介,安装和简单实例代码
2017/12/26 Python
python TF-IDF算法实现文本关键词提取
2019/05/29 Python
Python自动化导出zabbix数据并发邮件脚本
2019/08/16 Python
解决python明明pip安装成功却找不到包的问题
2019/08/28 Python
PyCharm使用之配置SSH Interpreter的方法步骤
2019/12/26 Python
浅谈Python中的模块
2020/06/10 Python
CSS3实现大小不一的粒子旋转加载动画
2016/04/21 HTML / CSS
用HTML5实现手机摇一摇的功能的教程
2012/10/30 HTML / CSS
LTD Commodities:礼品,独特发现,家居装饰,家用器皿
2017/08/11 全球购物
采购员的工作职责
2013/12/26 职场文书
便利店投资的创业计划书
2014/01/12 职场文书
会计核算科岗位职责
2014/03/19 职场文书
工程承包协议书范本
2014/09/29 职场文书
Redis Cluster 集群搭建你会吗
2021/08/04 Redis
vue如何实现关闭对话框后刷新列表
2022/04/08 Vue.js