前端MVC框架Backbone 1.1.0源码分析(二) - 模型

简介:

模型是什么?

Models are the heart of any JavaScript application, containing the interactive data as well as a large part of the logic surrounding it: conversions, validations, computed properties, and access control. You extend Backbone.Model with your domain-specific methods, and Model provides a basic set of functionality for managing changes.

模型 是所有 Javascript 应用程序的核心,包括交互数据及相关的大量逻辑: 转换、验证、计算属性和访问控制。

你可以用特定的方法扩展 Backbone.Model , 模型 也提供了一组基本的管理变化的功能,这个东西就像是后端开发中的数据库映射那个model一样,也是数据对象的模型,并且应该是和后端的model有相同的属性(仅是需要通过前端来操作的属性)。

简而言之,就是围绕着数据处理,如创建、校验、销毁和保存到服务端等等...

 


如何设计模型

之前说了,模型可以围绕数据处理类似curd的操作,所以backbone就为我们提供了这样的一个基础模板,Backbone中的模型类是Backbone.Model,它包含了数据存储,数据验证,以及数据发生变动时触发相关动作,我们只要继承就能使用这些特性了

用别人的框架,就需要了解别人的规则,这种学习成本是跑不掉的 - -

官方的demo

下面是一个示例,它演示了定义一个模型使用一个自定义的方法,设置一个属性,触发一个事件的特定属性的变化

复制代码
var Sidebar = Backbone.Model.extend({
    promptColor: function() {
        var cssColor = prompt("Please enter a CSS color:");
        this.set({color: cssColor});
    }
});

window.sidebar = new Sidebar;

sidebar.on('change:color', function(model, color) {
    console.log('修改颜色',color)
});

sidebar.set({color: 'white'});

sidebar.promptColor();
复制代码

当models中值被改变时自动触发一个"change"事件、所有用于展示models数据的views都会侦听到这个事件,然后进行重新渲染。

Backbone.Model 是Backbone提供模板类,通过继承extend构造自己Sidebar模型类

所以具有了on ,set 等等这种基础的属性与方法

 


Backbone.Model

模型构造器

那么我看看backbone模型类模板能为我们提供什么基础功能

  1. 既然是模型首先就是围绕数据操作,上帝set,上帝get不能少,这样也是为了体现出对象封装性
  2. 与此同时数据的清理与改变也是不能少的
  3. 监听对象中属性变化
  4. 为对象添加验证规则,以及错误提示
  5. 对象的获取和保存,需要服务器端支持才能测试
  6. 等等一些围绕的数据的处理了

 

 


继承extend

就是把模板类的方法继承给子类,所以我们子类都具有相同的特性了

Backbone.Model.extend

Backbone.Collection.extend

Backbone.Router.extend

Backbone.View.extend

 

扩充的静态方法

Model.extend = Collection.extend = Router.extend = View.extend = History.extend = extend;

关于这个继承很好理解,js的继承常用的就是这个了

代码简单分析下

创建子类的载体,换句话就是我们构造出来的那个新的类的一个新的构造器

复制代码
if (protoProps && _.has(protoProps, 'constructor')) {
    child = protoProps.constructor;
} else {
    child = function () {
        return parent.apply(this, arguments);
    };
}
复制代码

如果用户自定义了constructor函数,就用这个,否则就内部自行构建

之后就是复制静态属性到新的child

然后把父类的原型链的引用给指向child

这个请参考http://www.cnblogs.com/aaronjs/archive/2012/08/26/2657103.html

image

扩展了属性,在constructor中扩展了__super__ 指向父类,继承了模板的原型链上的方法

 


上帝get/上帝set

可以想像下模型实例用来存储数据表中的一行数据(row)

Backbone利用model的attributes与数据库的字段一一对应

使用set和get方法来设置或获取模型的属性。

复制代码
var Model = Backbone.Model = function (attributes, options) {
    var attrs = attributes || {};
    options || (options = {});
    this.cid = _.uniqueId('c');
    
this.attributes
 = {};
    if (options.collection) this.collection = options.collection;
    if (options.parse) attrs = this.parse(attrs, options) || {};
    attrs = _.defaults({}, attrs, _.result(this, 'defaults'));
    this.set(attrs, options);
    this.changed = {};
    this.initialize.apply(this, arguments);
};
复制代码

不能把属性直接写到 Backbone.Model.extend的扩展中,原因也很简单,一个是封装性,最重要的原型上是共享的,如果是引用类型就糟糕了

所以属性在模型实例上有一个专门的属性来存储:this.attributes,set/get都围绕this.attributes操作。

 


监听对象中属性的变化(change)

  Models 用来创建数据,校验数据,存储数据到服务器端.Models 还可以绑定事件。比如用户动作变化触发 models 的 change 事件,所有展示此model 数据的 views 都会接收到 这个 change 事件,进行重绘。

如果任何属性的改变模型的状态,“改变”事件将触发模式

只是实现了一个自定义事件功能

监听属性color的改变

sidebar.on('change:color', function(model, color) {
    console.log('修改颜色',color)
});

设置改变

sidebar.set({color: 'white'});

 

源码实现

Backbone.Model继承了自定义事件Events

_.extend(Model.prototype, Events, {});

sidebar实例继承了Backbone.Model.

var Sidebar = Backbone.Model.extend

所以Sidebar也具有自定义事件的功能,只是在set方法里面按照规则触发

使用 set() 方法创建或者设置属性值可以触发自定义事件,

复制代码
if (!silent) {
    if (changes.length) this._pending = options;
    for (var i = 0, l = changes.length; i < l; i++) {
        this.trigger('change:' + changes[i], this, current[changes[i]], options);
    }
}
复制代码

 

PS:

我们知道虽然属性是存储this.attributes中,但是如果是直接

实例.attributes.name = "属性名";

这样很明显就丢失了自定义事件了,所以使用 set() 是改变模型状态并触发其变更事件的唯一方法

Model 这一概念来对事件进行控制,但是这样很好的使我们将结构分离开,容易控制整体以及之后的变更都会变得异常简单。

 


为对象添加验证规则,以及错误提示

验证模型数据规范

复制代码
var Chapter = Backbone.Model.extend({
  validate: function(attrs, options) {
    if (attrs.end < attrs.start) {
      return "can't end before it starts";
    }
  }
});
复制代码

源码部分

复制代码
_validate: function (attrs, options) {
            if (!options.validate || !this.validate) return true;
            attrs = _.extend({}, this.attributes, attrs);
            var error = this.validationError = this.validate(attrs, options) || null;
            if (!error) return true;
            this.trigger('invalid', this, error, _.extend(options, {validationError: error}));
            return false;
        }
复制代码

执行了this.validate(attrs, options) 自定义验证函数,可见如果返回了true

就会执行this.trigger('invalid', this, error, _.extend(options, {validationError: error})); 错误通知了

余下的fetch,save,sync,url等等放在合集中在讲吧


本文转自艾伦 Aaron博客园博客,原文链接:http://www.cnblogs.com/aaronjs/p/3504571.html,如需转载请自行联系原作者

目录
打赏
0
0
0
0
51
分享
相关文章
(前端3D模型开发)网页三维CAD中加载和保存STEP模型
本文介绍了如何使用`mxcad3d`库在网页上实现STEP格式三维模型的导入与导出。首先,通过官方教程搭建基本项目环境,了解核心对象如MxCAD3DObject、Mx3dDbDocument等的使用方法。接着,编写了加载和保存STEP模型的具体代码,包括HTML界面设计和TypeScript逻辑实现。最后,通过运行项目验证功能,展示了从模型加载到保存的全过程。此外,`mxcad3d`还支持多种其他格式的三维模型文件操作。
颠覆传统:React框架如何引领前端开发的革命性变革
【10月更文挑战第32天】本文以问答形式探讨了React框架的特性和应用。React是一款由Facebook推出的JavaScript库,以其虚拟DOM机制和组件化设计,成为构建高性能单页面应用的理想选择。文章介绍了如何开始一个React项目、组件化思想的体现、性能优化方法、表单处理及路由实现等内容,帮助开发者更好地理解和使用React。
104 9
圈子社交app前端+后端源码,uniapp社交兴趣圈子开发,框架php圈子小程序安装搭建
本文介绍了圈子社交APP的源码获取、分析与定制,PHP实现的圈子框架设计及代码编写,以及圈子小程序的安装搭建。涵盖环境配置、数据库设计、前后端开发与接口对接等内容,确保平台的安全性、性能和功能完整性。通过详细指导,帮助开发者快速搭建稳定可靠的圈子社交平台。
一款基于 .NET MVC 框架开发、功能全面的MES系统
一款基于 .NET MVC 框架开发、功能全面的MES系统
前端界的秘密武器:掌握这些框架,让你轻松秒杀99%的同行!
前端开发日新月异,掌握几个明星框架如React、Vue.js和Angular,不仅能让工作更得心应手,还能轻松超越同行。React以高效的虚拟DOM和组件化著称;Vue.js简洁易懂,灵活性高;Angular提供全面的解决方案,适合大型应用。此外,轻量级的Svelte也值得关注,其编译时处理设计提升了应用性能。掌握这些框架,结合深刻理解和灵活运用,助你在前端领域脱颖而出。
43 9
前端全栈之路Deno篇(五):如何快速创建 WebSocket 服务端应用 + 客户端应用 - 可能是2025最佳的Websocket全栈实时应用框架
本文介绍了如何使用Deno 2.0快速构建WebSocket全栈应用,包括服务端和客户端的创建。通过一个简单的代码示例,展示了Deno在WebSocket实现中的便捷与强大,无需额外依赖,即可轻松搭建具备基本功能的WebSocket应用。Deno 2.0被认为是最佳的WebSocket全栈应用JS运行时,适合全栈开发者学习和使用。
183 7
Spring MVC源码分析之DispatcherServlet#getHandlerAdapter方法
`DispatcherServlet`的 `getHandlerAdapter`方法是Spring MVC处理请求的核心部分之一。它通过遍历预定义的 `HandlerAdapter`列表,找到适用于当前处理器的适配器,并调用适配器执行具体的处理逻辑。理解这个方法有助于深入了解Spring MVC的工作机制和扩展点。
46 1
Spring MVC源码分析之DispatcherServlet#getHandlerAdapter方法
`DispatcherServlet`的 `getHandlerAdapter`方法是Spring MVC处理请求的核心部分之一。它通过遍历预定义的 `HandlerAdapter`列表,找到适用于当前处理器的适配器,并调用适配器执行具体的处理逻辑。理解这个方法有助于深入了解Spring MVC的工作机制和扩展点。
45 1
前端serverless探索之组件单独部署时,利用rxjs实现业务状态与vue-react-angular等框架的响应式状态映射
本文深入探讨了如何将RxJS与Vue、React、Angular三大前端框架进行集成,通过抽象出辅助方法`useRx`和`pushPipe`,实现跨框架的状态管理。具体介绍了各框架的响应式机制,展示了如何将RxJS的Observable对象转化为框架的响应式数据,并通过示例代码演示了使用方法。此外,还讨论了全局状态源与WebComponent的部署优化,以及一些实践中的改进点。这些方法不仅简化了异步编程,还提升了代码的可读性和可维护性。
105 1
前端全栈之路Deno篇(四):Deno2.0如何快速创建http一个 restfulapi/静态文件托管应用及oak框架介绍
Deno 是由 Node.js 创始人 Ryan Dahl 开发的新一代 JavaScript 和 TypeScript 运行时,旨在解决 Node.js 的设计缺陷,具备更强的安全性和内置的 TypeScript 支持。本文介绍了如何使用 Deno 内置的 `Deno.serve` 快速创建 HTTP 服务,并详细讲解了 Oak 框架的安装和使用方法,包括中间件、路由和静态文件服务等功能。Deno 和 Oak 的结合使得创建 RESTful API 变得高效且简便,非常适合快速开发和部署现代 Web 应用程序。
162 2