Web 前端框架学习 - Backbone,React

关于框架和库

jQuery 和 Backbone 的区别?

jQuery 通常是作为工具(或工具的仓库)来用的,用 jQuery 是为了更方便,代码更短、更简单。

Backbone 则是体现了一种构建 Web 页面/程序的思想,将应用程序进行分层,数据操作是一个层面,UI/视图是一个层面。数据层的代码不需要知道UI/视图的存在,不关心样式展现、界面交互的细节;视图层的代码不关心数据是如何获取、处理的,关系如何展现这些数据,并将用户交互操作转交给数据层进行处理,而在数据发生变更时负责更新页面。

作为框架的 Backbone

Web 前端框架学习 - Backbone,React_第1张图片
Models and Views - from backbonejs.org

相对于库,框架给出了一个应用程序大体架构,对代码如何按照职能进行分层、分块给出了建议/规定。开发新的程序时,开发者要遵循框架的各项原则编写各部分代码。

例如,对于 Backbone,如果我要从后台请求数据,这部分代码我会放到 Model 或 Collection(其实是 Model 的集合)中,而响应用户对按钮点击的代码则放到 View 中。如果在 View 中我编写了发送 Ajax 请求的代码,通常来说是不好的模式(反模式)。

框架甚至可以让开发者只负责“填充代码”,由框架来调用开发者提供的代码从而实现程序的运行。而对于库,则是开发者来主动调用库。框架的这种特性,称为“控制反转”(IOC)。不过对于 Backbone,开发者还是需要自己干很多事情,并没有一种 Backbone 接管了程序的运行的感觉,如果想体验这种感觉,AngularJS 应该比较像。

我理解的 Backbone

注意上图(Models and Views),数据层(Model)有数据变更了,但并不知道关于视图(View)的细节,视图如何根据变化后的数据更新页面呢?

这里涉及到数据是如何流动的。

在 Backbone 中,这个比较简单,和上图类似,Model -> View。不过 View 实际上还会修改数据,View -> Model。当然,从“可视性”上来看,Model 看不到 View,View 看得见 Model。View 通过监听 Model 的事件来知晓 Model 发生的变化。Model 在自身数据改变后,只需要触发相应的事件来通知 View 即可,但这是 View 主动发起的监听,Model 并不知道是谁在监听。

查看 Backbone 的源码,第一大部分即是 Event 系统的定义。无论是 Backbone.Model, Backbone.View 还是 Backbone.Collection 都继承了 Event,也就是都有发布事件的能力。最主要的用途应该就是 Model 在数据变化时通知 View 的这种情况了。

所以,我理解的 Backbone 主要是三方面:

  1. 事件机制
  2. 数据层 Model
  3. 视图层 View

至于 Backbone.Collection 和 Backbone.Router,都是工具嘛。

我理解的 React

再来看 React,和 Backbone 这种 MV* 框架的最大区别在于:React 并非是遵循 MVC 架构设计出来的!

在我看来,React 要解决的是快速开发可复用的 UI 组件的问题。从这个角度来看,React 甚至不算是完成的框架。Facebook 还提供了 Flux,算是对 React 的补充。Flux 是一个完成的应用架构的理念,React 在其中是作为 View 存在的。

来看 Flux 的结构和数据流图:

Web 前端框架学习 - Backbone,React_第2张图片
Structure and Data Flow - from http://facebook.github.io/flux/docs/overview.html

Flux 被设计为单向的数据流,Store 中的数据,可以被 View 获取,但 View 并不直接对 Store 进行操作。View 接收的用户交互,可能会导致数据变更,此时创建一个 Action。各种类型的 Action 汇总到一个全局的 Dispatcher 中,由 Dispatcher 再进一步转发给关心的 Store,Store 如果变更了,View 会通过事件获得通知,从而进一步更新界面显示。

绕这么一圈,有点蛋疼吧?

不过 Facebook 在相关文档中给出了这样设计的原因和优势,我理解的一个主要的原因应该是单向的数据流 —— 简单!

将 React 放在 Flux 的提供的架构里来看,就比较容易理解 React 的特性了。React 被设计为整体渲染的方式,也就是说,如果一部分数据发送变化,也不会单独渲染页面上的一部分,而是直接调用渲染函数全部刷新。

这样做的话固然简单了很多,但是性能岂不是很差?

React 的解决方案是:别怕,不是真的重新渲染一般,底层会对比新生成的 DOM 和已有的 DOM 的差别,智能地更新改变的部分。所以在 React 中有 Virtual DOM 的存在,直接操作的并不是真实的 DOM。这么一来,代码简单了,性能问题据说也不用担心。

React 的 UI 组件中,不能修改获取的数据,这个特性从 Flux 里可以看出,Facebook 希望数据是单向流动的嘛,所以 View 中的数据视为不可修改的。想修改?创建一个 Action 嘛。

其实在 Flux 工程中,只是实现了 Dispatcher,对于 Action 和 Store 并没有缺省的实现。Action,其实就是一个结构化数据对象,调用 Dispatcher 时传入。从 Flux 项目的示例应用 TodoMVC 中可以看到,Action 的代码,准确来说是 Action Creator,用于创建 Action 发送给 Dispatcher。而 Store,Facebook 说只要实现了事件订阅、发布就行,示例应用是采用了 Node.js 的 EventEmitter,也可以用其他的事件模型替换。

有一个问题:在各层面与后台产生联系,获取、更新数据呢?

View,也就是 React 的部分应该要排除,在 Flux 的体系里,它不应该操作数据。Dispatcher 其实只管转发 Action 给 Store 处理,本身不处理数据。所以是 Action 和 Store 中的一个。

Action 本身只是数据,或者消息数据,如果携带有数据,应该是创建 Action 的模块来请求数据。

Store 的话如果干这件事就很自然了,请求数据,更新自身,触发事件,View 响应....

Facebook 推荐,或者说设计的模式的怎样的呢?

查看 Flux 示例应用 Chat Client,答案是:都不是!

有一个 utils/ChatWebAPIUtils.js 来模拟与服务器的交互(实际是使用 LocalStorage 存取数据),获取新的数据后,通过 Action 发布,看代码:

// flux-master\examples\flux-chat\js\utils\ChatWebAPIUtils.js
// line 50
    setTimeout(function() {
      ChatServerActionCreators.receiveCreatedMessage(createdMessage);
    }, 0);

所以,我揣测 Facebook 推荐的方式,哪里也不放!把与服务器交互的代码单独写到一个模块里面,供其他模块调用。初始获取数据的操作应该是在 app.js 这样的入口模块中,更新方面的调用应该还是会在 Store 里面吧。

其他

Backbone 是实际工作中用过的,不过是自己琢磨着用,是否规范就不得而知啦。对于 Backbone 的理解当然也是我自己琢磨的。

React 并未在实际工作中,说实话也只是这两天花时间学习了下,感觉自己算算入门了。在学习 React 的时候有很多疑问,后来在看到 Flux 之后才算解惑了,压根 React 就没想着独挡一门,作为完整的框架使用,遵循 Flux 的架构的话就比较完整了。

你可能感兴趣的:(Web 前端框架学习 - Backbone,React)