作者: 京东零售 陈震

一、 什么是Backbone

在前端的发展道路中,前端框架元老之一jQuery对繁琐的DOM操作进行了封装,提供了链式调用、各类选择器,屏蔽了不同浏览器写法的差异性,但是前端开发过程中依然存在作用域污染、代码复用度低、冗余度高、数据和事件绑定烦琐等痛点。

5年后,Backbone横空出世,通过与Underscore、Require、Handlebar的整合,提供了一个轻量和友好的前端开发解决方案,其诸多设计思想对于后续的现代化前端框架发展起到了举足轻重的作用,堪称现代前端框架的基石。

通过对Backbone前端框架的学习,让我们领略其独特的设计思想。

二、 核心架构

按照MVC框架的定义,MVC是用来将应用程序分为三个主要逻辑组件的架构模式:模型,视图和控制器。这些组件被用来处理一个面向应用的特定开发。 MVC是最常用的行业标准的Web开发框架,以创建可扩展的项目之一。 Backbone.js为复杂WEB应用程序提供模型(models)、集合(collections)、视图(views)的结构。

◦ 其中模型用于绑定键值数据,并通过RESRful JSON接口连接到应用程序;

◦ 视图用于UI界面渲染,可以声明自定义事件,通过监听模型和集合的变化执行相应的回调(如执行渲染)。

如图所示,当用户与视图层产生交互时,控制层监听变化,负责与数据层进行数据交互,触发数据Change事件,从而通知视图层重新渲染,以实现UI界面更新。更进一步,当数据层发生变化时,由Backbone提供了数据层和服务器数据共享同步的能力。

其设计思想主要包含以下几点:

◦数据绑定(依赖渲染模板引擎)、事件驱动(依赖Events)

◦视图组件化,并且组件有了生命周期的概念

◦前端路由配置化,实现页面局部刷新

这些创新的思想,在现代前端框架中进一步得到了继承和发扬。

三、 部分源码解析

Backbone极度轻量,编译后仅有几kb,贯穿其中的是大量的设计模式:工厂模式、观察者模式、迭代器模式、适配器模式……,代码流畅、实现过程比较优雅。按照功能拆分为了Events、Model、Collection、Router、History、View等若干模块,这里摘取了部分精彩源码进行了解析,相信对我们的日常代码开发也有一定指导作用:

(1)迭代器

EventsApi起到一个迭代器分流的作用,对多个事件进行解析拆分,设计的非常经典,执行时以下用法都是合法的:

◦用法一:传入一个名称和回调函数的对象

modal.on({
"change": change_callback,
"remove": remove_callback
})

◦用法二:使用空格分割的多个事件名称绑定到同一个回调函数上

model.on("change remove", common_callback)

实现如下:

var eventsApi = function(iteratee, events, name, callback, opts) {
var i = 0, names;
if(name && typeof name === 'object') {
// 处理第一种用法
if(callback !== void 0 && 'context' in opts && opts.context === void 0) opts.context = callback;
for(names = _.keys(names); i < names.length; i++) events = eventsApi(iteratee, events, names[i], name[names[i]], opts);
} else if(name && eventSplitter.test(name)) {
// 处理第二种用法
for(names = name.split(eventSplitter); i < names.length; i++) events = iteratee(events, names[i], callback, opts);
} else {
events = iteratee(events, name, callback, opts);
}
return events;
}

(2)监听器

用于一个对象监听另外一个对象的事件,例如,在A对象上监听在B对象上发生的事件,并且执行A的回调函数:

A.listenTo(B, "b", callback)

实际上这个功能用B对象来监听也可以实现:

B.on("b", callback, A)

这么做的好处是,方便对A创建、销毁逻辑的代码聚合,并且对B的侵入程度较小。实现如下:

Events.listenTo = function(obj, name, callback) {
if(!obj) return this;
var id = obj._listenId || (obj._listenId = _.uniqueId('l'));
// 当前对象的所有监听对象
var listeningTo = this._listeningTo || (this._listeningTo = {});
var listening = listeningTo[id]; if(!listening) {
// 创建自身监听id
var thisId = this._listenId || (this._listenId = _.uniqueId('l'));
listening = listeningTo[id] = {obj: obj, objId: id, id: thisId, listeningTo: listeningTo, count: 0};
}
// 执行对象绑定
internalOn(obj, name, callback, this, listening);
return this;
}

(3)Model值set

通过option-flags兼容赋值、更新、删除等操作,这么做的好处是融合公共逻辑,简化代码逻辑和对外暴露api。实现如下:

set: function(key, val, options) {
if(key == null) return this;
// 支持两种赋值方式: 对象或者 key\value
var attrs;
if(typeof key === 'object') {
attrs = key;
options = val;
} else {
(attrs = {})[key] = val;
}
options || (options = {});
……
var unset = options.unset;
var silent = options.silent;
var changes = [];
var changing = this._changing; // 处理嵌套set
this._changing = true; if(!changing) {
// 存储变更前的状态快照
this._previousAttributes = _.clone(this.attributes);
this.changed = {};
}
var current = this.attributes;
var changed = this.changed;
var prev = this._previousAttributes; for(var attr in attrs) {
val = attrs[attr];
if(!_.isEqual(current[attr], val)) changes.push(attr);
// changed只存储本次变化的key
if(!_.isEqual(prev[attr], val)) {
changed[attr] = val;
} else {
delete changed[attr]
}
unset ? delete current[attr] : (current[attr] = val)
}
if(!silent) {
if(changes.length) this._pending = options;
for(var i=0; i<changes.length; i++) {
// 触发 change:attr 事件
this.trigger('change:' + changes[i], this, current[changes[i]], options);
}
}
if(changing) return this;
if(!silent) {
// 处理递归change场景
while(this._pending) {
options = this._pending;
this._pending = false;
this.trigger('change', this, options);
}
}
this._pending = false;
this._changing = false;
return this;
}

四、 不足(对比react、vue)

对比现代前端框架,由于Backbone本身比较轻量,对一些内容细节处理不够细腻,主要体现在:

◦视图和数据的交互关系需要自己分类编写逻辑,需要编写较多的监听器

◦监听器数量较大,需要手动销毁,维护成本较高

◦视图树的二次渲染仅能实现组件整体替换,并非增量更新,存在性能损失

◦路由切换需要自己处理页面更新逻辑

五、为什么选择Backbone

看到这里,你可能有些疑问,既然Backbone存在这些缺陷,那么现在学习Backbone还有什么意义呢?

首先,对于服务端开发人员,Backbone底层依赖underscore/lodash、jQuery/Zepto,目前依然有很多基于Jquery和Velocity的项目需要维护,会jQuery就会Backbone,学习成本低;通过Backbone能够学习用数据去驱动View更新,优化jQuery的写法;Backbone面对对象编程,符合Java开发习惯。

其次,对于前端开发人员,能够学习其模块化封装库类函数,提升编程技艺。Backbone的组件化开发,和现代前端框架有很多共通之处,能够深入理解其演化历史。

Backbone前端框架解读的更多相关文章

  1. backbone前端基础框架搭建

    前端站点名为:site: 前端框架分为:css.js和img,框架的核心在js文件夹下: js中包括collections.models.views.lib和一个app入口js

  2. 如何选择前端框架:ANGULAR VS EMBER VS REACT

    最近一段时间是令前端工程师们非常兴奋的时期,因为三大Web框架陆续发布新版本,让我们见识到了更强大的Web框架.Ember2.0在2个月之前已经发布,从1.0升级到2.0非常简单.几周之前React发 ...

  3. 2017年 JavaScript 框架回顾 -- 前端框架

    概述: 对于 JavaScript 社区来说,npm 的主要功能之一就是帮助开发者发掘所需的 npm Registry 中的库和框架.npm 强大的搜索功能能够帮助找到一组相关的软件包,同时其内置的的 ...

  4. 目前比较火的前端框架及UI组件

    看到的一篇总结性的文章,收藏一下,感兴趣的可以自己看看,哪些是已经会的,哪些是没听说过的,哪些是一知半解的,都可以稍微看看. 一.前端框架库: 1.Zepto.js 地址:点击打开链接 描述:Zept ...

  5. 5大JavaScript前端框架简介

    译者按: 简要介绍五大前端框架特性 原文: Top 5 JavaScript Frameworks 译者: Fundebug 为了保证可读性,本文采用意译而非直译.另外,本文版权归原作者所有,翻译仅用 ...

  6. [web前端] 去哪儿网前端架构师司徒正美:如何挑选适合的前端框架?

    原文地址: https://www.jianshu.com/p/6327d4280e3b 最近几年,前端技术迅猛发展,差不多每年都会冒出一款主流的框架. 每次新开业务线或启动新项目时,首先第一件事就是 ...

  7. Web前端,HTML5开发,前端资源,前端网址,前端博客,前端框架整理 - 转改

    Web前端/H5开发,前端资源,前端网址,前端博客,前端框架整理 综合类 前端知识体系 前端知识结构 Web前端开发大系概览 Web前端开发大系概览-中文版 Web Front-end Stack v ...

  8. (转)2018几大主流的UI/JS框架——前端框架 [Vue.js(目前市场上的主流)]

    https://blog.csdn.net/hu_belif/article/details/81258961 2016年开始应该是互联网飞速发展的几年,同时也是Web前端开发非常火爆的一年,Web ...

  9. 前端框架(kraken、Express、Node、MVC)

    You know my loneliness is only kept for you, my sweet songs are only sang for you. 前端框架相关知识记录. krake ...

  10. 全面解析JavaScript的Backbone.js框架中的Router路由

    这篇文章主要介绍了Backbone.js框架中的Router路由功能,Router在Backbone中相当于一个MVC框架中的Controller控制器功能,需要的朋友可以参考下. Backbone ...

随机推荐

  1. AGC007C Pushing Balls —— 期望的神题

    Problem Link 题意: 序列上按顺序交错有 \(n\) 个球和 \(n+1\) 个洞,即 \(hole_1,ball_1,hole_2,ball_2,\dots,ball_n,hole_{n ...

  2. C#11之原始字符串

    最近.NET7.0和C#11相继发布,笔者也是第一时间就用上了C#11,其中C#11的有一个更新能解决困扰我多年的问题,也就是文章的标题原始字符串. 在使用C#11的原始字符串时,发现的一些有意思的东 ...

  3. 如何在JavaScript中使用for循环

    前言 循环允许我们通过循环数组或对象中的项并做一些事情,比如说打印它们,修改它们,或执行其他类型的任务或动作.JavaScript有各种各样的循环,for循环允许我们对一个集合(如数组)进行迭代. 在 ...

  4. HTTPS - 揭秘 TLS 1.2 协议完整握手过程--此文为转发文,一定要结合wirshark工具看,很清楚

    winshark 筛选条件为:tls and ip.src==xxx 本文通过对一次 TLS 握手过程的数据抓包分析做为切入点,希望能进一步的帮助大家理解 HTTPS 原理. HTTPS 是建立在 S ...

  5. 165 pbi-utils 使用文档

    165 pbi-utils 使用文档 一.背景 先来说一下为什么会有 pbi-utils 这个小工具吧.在我日常做演示的示例文件的时候,每次都要重新搞一次 Power BI Desktop,就想能不能 ...

  6. 使用pandas处理数据和matplotlib生成可视化图表

    一.缘由 上一篇输入关键词"口红",将淘宝中的的相关商品信息全部爬取了下拉,并且以CSV的文件格式储存.我们拿到数据之后,那么就需要对数据进行处理.只是将爬取到的数据以更直观的方式 ...

  7. UBOOT 启动流程

    一.概述 uboot 的启动流程在网上有很多大佬记录,但是了对于像我这样的新手就有些困难了,而我也不做 uboot 相关的工作,所以没必去研究代码,这里我特意整理了一下,以流程图的形式展现代码执行的流 ...

  8. 【数据结构与算法】希尔排序 python和c++实现

    算法思路 每一次:固定间隔把数据分组,每一组进行排序 每次比上次选取更小的间隔分组,再每组排序,直到间隔为1 代码 c++:(越看越不明白了,后看) int gap = length;//length ...

  9. Golang Gorm 封装 分页查询 Where Order 查询

    说说为什么写Gorm,因为公司新项目需要,研究了下Go下的gorm.对于一个项目首先考虑的问题,就是封装一些常用的工具方法,例如多参数查询 where or Like 还有order by Limit ...

  10. MySQL简介、下载、密码修改及基本使用

    目录 存取数据的演变史 数据库软件应用史 数据库的本质 数据库的分类 MySQL简介 MySQL基本使用 系统服务的制作 密码相关操作 SQL与NoSQL 数据库重要概念 基本SQL语句 存取数据的演 ...