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 相关文章推荐
简单的邮箱登陆的提示效果类似于yahoo邮箱
Feb 26 Javascript
JavaScript中用于四舍五入的Math.round()方法讲解
Jun 15 Javascript
jquery插件pagination实现无刷新ajax分页
Sep 30 Javascript
jQuery+canvas实现的球体平抛及颜色动态变换效果
Jan 28 Javascript
JQuery给select添加/删除节点的实现代码
Apr 26 Javascript
Bootstrap中的fileinput 多图片上传及编辑功能
Sep 05 Javascript
前端弹出对话框 js实现ajax交互
Sep 09 Javascript
jQuery动态增减行的实例代码解析(推荐)
Dec 05 Javascript
Bootstrap表格使用方法详解
Feb 17 Javascript
在webstorm开发微信小程序之使用阿里自定义字体图标的方法
Nov 15 Javascript
vuex 解决报错this.$store.commit is not a function的方法
Dec 17 Javascript
一百行JS代码实现一个校验工具
Apr 30 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 模拟$_PUT实现代码
2010/03/15 PHP
深入Apache与Nginx的优缺点比较详解
2013/06/17 PHP
php根据年月获取季度的方法
2014/03/31 PHP
php学习笔记之面向对象
2014/11/08 PHP
php使用MySQL保存session会话的方法
2015/06/18 PHP
PHP+AJAX实现投票功能的方法
2015/09/28 PHP
PHP大文件分割上传 PHP分片上传
2017/08/28 PHP
IE中radio 或checkbox的checked属性初始状态下不能选中显示问题
2009/07/25 Javascript
JavaScript创建类/对象的几种方式概述及实例
2013/05/06 Javascript
jQuery解决下拉框select设宽度时IE 6/7/8下option超出显示不全
2013/05/27 Javascript
js实现倒计时时钟的示例代码
2013/12/17 Javascript
如何防止回车(enter)键提交表单
2014/05/11 Javascript
从JQuery源码分析JavaScript函数的apply方法与call方法
2014/09/25 Javascript
在线所见即所得HTML编辑器的实现原理浅析
2015/04/25 Javascript
使用jQuery UI库开发Web界面的简单入门指引
2016/04/22 Javascript
jQuery轻松实现表格的隔行变色和点击行变色的实例代码
2016/05/09 Javascript
全国省市二级联动下拉菜单 js版
2016/05/10 Javascript
javascript判断回文数详解及实现代码
2017/02/03 Javascript
ComboBox(下拉列表框)通过url加载调用远程数据的方法
2017/08/06 Javascript
vue里input根据value改变背景色的实例
2018/09/29 Javascript
Vue2.x通用编辑组件的封装及应用详解
2019/05/28 Javascript
基于jquery实现的tab选项卡功能示例【附源码下载】
2019/06/10 jQuery
微信小程序实现转盘抽奖
2020/09/21 Javascript
Python多线程编程(三):threading.Thread类的重要函数和方法
2015/04/05 Python
Python中的左斜杠、右斜杠(正斜杠和反斜杠)
2016/08/30 Python
python3处理含有中文的url方法
2018/05/10 Python
Python之关于类变量的两种赋值区别详解
2020/03/12 Python
俄罗斯旅游网站:Tripadvisor俄罗斯
2017/03/21 全球购物
运行时异常与一般异常有何异同?
2014/01/05 面试题
日语系毕业生推荐信
2013/11/11 职场文书
八项规定对照检查材料
2014/08/31 职场文书
2014年语文教研组工作总结
2014/12/06 职场文书
2016春节慰问信范文
2015/03/25 职场文书
2015年保育员个人工作总结
2015/05/13 职场文书
2016年感恩节活动总结大全
2016/04/01 职场文书
python绘制简单直方图(质量分布图)的方法
2022/04/21 Python