前端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,如需转载请自行联系原作者

相关文章
|
2月前
|
JavaScript 前端开发 开发者
Vue.js 框架大揭秘:响应式系统、组件化与路由管理,震撼你的前端世界!
【8月更文挑战第27天】Vue.js是一款备受欢迎的前端JavaScript框架,以简洁、灵活和高效著称。本文将从三个方面深入探讨Vue.js:响应式系统、组件化及路由管理。响应式系统为Vue.js的核心特性,能自动追踪数据变动并更新视图。例如,通过简单示例代码展示其响应式特性:`{{ message }}`,当`message`值改变,页面随之自动更新。此外,Vue.js支持组件化设计,允许将复杂界面拆分为独立且可复用的组件,提高代码可维护性和扩展性。如创建一个包含标题与内容的简单组件,并在其他页面中重复利用。
58 3
|
8天前
|
前端开发 JavaScript API
React、Vue.js 和 Angular前端三大框架对比与选择
前端框架是用于构建用户界面的工具和库,它提供组件化结构、数据绑定、路由管理和状态管理等功能,帮助开发者高效地创建和维护 web 应用的前端部分。常见的前端框架如 React、Vue.js 和 Angular,能够提高开发效率并促进团队协作。
25 4
|
15天前
|
机器学习/深度学习 数据采集 JavaScript
ADR智能监测系统源码,系统采用Java开发,基于SpringBoot框架,前端使用Vue,可自动预警药品不良反应
ADR药品不良反应监测系统是一款智能化工具,用于监测和分析药品不良反应。该系统通过收集和分析病历、处方及实验室数据,快速识别潜在不良反应,提升用药安全性。系统采用Java开发,基于SpringBoot框架,前端使用Vue,具备数据采集、清洗、分析等功能模块,并能生成监测报告辅助医务人员决策。通过集成多种数据源并运用机器学习算法,系统可自动预警药品不良反应,有效减少药害事故,保障公众健康。
ADR智能监测系统源码,系统采用Java开发,基于SpringBoot框架,前端使用Vue,可自动预警药品不良反应
|
27天前
|
Web App开发 前端开发 JavaScript
Web前端项目的跨平台桌面客户端打包方案之——CEF框架
Chromium Embedded Framework (CEF) 是一个基于 Google Chromium 项目的开源 Web 浏览器控件,旨在为第三方应用提供嵌入式浏览器支持。CEF 隔离了底层 Chromium 和 Blink 的复杂性,提供了稳定的产品级 API。它支持 Windows、Linux 和 Mac 平台,不仅限于 C/C++ 接口,还支持多种语言。CEF 功能强大,性能优异,广泛应用于桌面端开发,如 QQ、微信、网易云音乐等。CEF 开源且采用 BSD 授权,商业友好,装机量已超 1 亿。此外,GitHub 项目 CefDetector 可帮助检测电脑中使用 CEF
104 3
|
2月前
|
开发者 安全 UED
JSF事件监听器:解锁动态界面的秘密武器,你真的知道如何驾驭它吗?
【8月更文挑战第31天】在构建动态用户界面时,事件监听器是实现组件间通信和响应用户操作的关键机制。JavaServer Faces (JSF) 提供了完整的事件模型,通过自定义事件监听器扩展组件行为。本文详细介绍如何在 JSF 应用中创建和使用事件监听器,提升应用的交互性和响应能力。
22 0
|
2月前
|
API UED 开发者
如何在Uno Platform中轻松实现流畅动画效果——从基础到优化,全方位打造用户友好的动态交互体验!
【8月更文挑战第31天】在开发跨平台应用时,确保用户界面流畅且具吸引力至关重要。Uno Platform 作为多端统一的开发框架,不仅支持跨系统应用开发,还能通过优化实现流畅动画,增强用户体验。本文探讨了Uno Platform中实现流畅动画的多个方面,包括动画基础、性能优化、实践技巧及问题排查,帮助开发者掌握具体优化策略,提升应用质量与用户满意度。通过合理利用故事板、减少布局复杂性、使用硬件加速等技术,结合异步方法与预设缓存技巧,开发者能够创建美观且流畅的动画效果。
57 0
|
2月前
|
前端开发 开发者 Apache
揭秘Apache Wicket项目结构:如何打造Web应用的钢铁长城,告别混乱代码!
【8月更文挑战第31天】Apache Wicket凭借其组件化设计深受Java Web开发者青睐。本文详细解析了Wicket项目结构,帮助你构建可维护的大型Web应用。通过示例展示了如何使用Maven管理依赖,并组织页面、组件及业务逻辑,确保代码清晰易懂。Wicket提供的页面继承、组件重用等功能进一步增强了项目的可维护性和扩展性。掌握这些技巧,能够显著提升开发效率,构建更稳定的Web应用。
76 0
|
2月前
|
前端开发 程序员 API
从后端到前端的无缝切换:一名C#程序员如何借助Blazor技术实现全栈开发的梦想——深入解析Blazor框架下的Web应用构建之旅,附带实战代码示例与项目配置技巧揭露
【8月更文挑战第31天】本文通过详细步骤和代码示例,介绍了如何利用 Blazor 构建全栈 Web 应用。从创建新的 Blazor WebAssembly 项目开始,逐步演示了前后端分离的服务架构设计,包括 REST API 的设置及 Blazor 组件的数据展示。通过整合前后端逻辑,C# 开发者能够在统一环境中实现高效且一致的全栈开发。Blazor 的引入不仅简化了 Web 应用开发流程,还为习惯于后端开发的程序员提供了进入前端世界的桥梁。
50 0
|
2月前
|
前端开发 JavaScript 中间件
【前端状态管理之道】React Context与Redux大对决:从原理到实践全面解析状态管理框架的选择与比较,帮你找到最适合的解决方案!
【8月更文挑战第31天】本文通过电子商务网站的具体案例,详细比较了React Context与Redux两种状态管理方案的优缺点。React Context作为轻量级API,适合小规模应用和少量状态共享,实现简单快捷。Redux则适用于大型复杂应用,具备严格的状态管理规则和丰富的社区支持,但配置较为繁琐。文章提供了两种方案的具体实现代码,并从适用场景、维护成本及社区支持三方面进行对比分析,帮助开发者根据项目需求选择最佳方案。
22 0
|
2月前
|
前端开发 JavaScript 测试技术
React 与前端自动化测试也太重要啦!各种测试框架助力确保应用质量,快来开启优质开发之旅!
【8月更文挑战第31天】随着前端技术的发展,React 成为了构建用户界面的热门选择。然而,随着应用复杂性的增加,确保应用质量变得至关重要。本文介绍了前端自动化测试的重要性,并详细综述了常用的测试框架如 Jest、Enzyme 和 Cypress,以及如何通过它们进行高效的 React 组件测试。通过遵循最佳实践,如编写可维护的测试用例、覆盖关键场景、集成 CI/CD 流程和进行性能测试,可以显著提高应用的稳定性和可靠性。
43 0
下一篇
无影云桌面