Backbone View 之间通信的三种方式

所属分类: 网络编程 / JavaScript 阅读数: 1906
收藏 0 赞 0 分享

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

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

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

 

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

 

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

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

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

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

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

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

1. 通过父视图传递事件

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

 

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 。把它注入到各个子视图中,用来广播事件。

 

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 对象可以直接调用,这样我就不必在每个子视图中手动注入它了。

 

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 对象,但是用起来却异常简洁。

更多精彩内容其他人还在看

Angular使用Md5加密的解决方法

这篇文章主要介绍了Angular使用Md5加密的解决方法,需要的朋友可以参考下
收藏 0 赞 0 分享

详解JS构造函数中this和return

本文通过实例代码给大家介绍了JS构造函数中this和return,需要的朋友参考下吧
收藏 0 赞 0 分享

ES6中Array.find()和findIndex()函数的用法详解

ES6为Array增加了find(),findIndex函数。find()函数用来查找目标元素,找到就返回该元素,找不到返回undefined,而findIndex()函数也是查找目标元素,找到就返回元素的位置,找不到就返回-1。下面通过实例详解,需要的朋友参考下吧
收藏 0 赞 0 分享

JS闭包的几种常见形式实例详解

本文通过实例代码给大家详细介绍了js闭包的几种常见形式,代码简单易懂,非常不错,具有参考借鉴价值,需要的朋友参考下
收藏 0 赞 0 分享

ES6中Array.copyWithin()函数的用法实例详解

ES6为Array增加了copyWithin函数,用于操作当前数组自身,用来把某些个位置的元素复制并覆盖到其他位置上去。下面重点给大家介绍ES6中Array.copyWithin()函数的用法,需要的朋友参考下
收藏 0 赞 0 分享

Javascript 严格模式use strict详解

严格模式:由ECMA-262规范定义的JavaScript标准,对javascrip的限制更强。这篇文章主要介绍了Javascript 严格模式use strict详解 ,需要的朋友可以参考下
收藏 0 赞 0 分享

引入JavaScript时alert弹出框显示中文乱码问题

今天在HTML中引入JavaScript文件运行时,alert弹出的提示框中文显示为乱码,怎么解决此问题呢?下面小编给大家带来了引入JavaScript时alert弹出框显示中文乱码问题的解决方法,一起看看吧
收藏 0 赞 0 分享

AngularJs 延时器、计时器实例代码

这篇文章主要介绍了AngularJs 延时器、计时器实例代码,需要的朋友可以参考下
收藏 0 赞 0 分享

JS分页的实现(同步与异步)

这篇文章主要介绍了JS分页的实现(同步与异步),需要的朋友可以参考下
收藏 0 赞 0 分享

Angularjs自定义指令实现分页插件(DEMO)

由于最近的一个项目使用的是angularjs1.0的版本,涉及到分页查询数据的功能,后来自己就用自定义指令实现了该功能,下面小编把实例demo分享到脚本之家平台,需要的朋友参考下
收藏 0 赞 0 分享
查看更多