2019独角兽企业重金招聘Python工程师标准>>>

ExtJS4 API文档阅读(四)——Data

数据

Data包负责加载和保存你应用程序中的所有数据,由41个类构成,其中有三个类是最重要的,分别是模型类(Model),存储类(Store),代理类(Ext.data.proxy.Proxy)。它们几乎在每个应用程序中都被使用到,并且有很多相附类为它们提供支持。

模型类和存储类

模型类(Ext.data.Model)是data包的核心部件。每个模型代表应用程序中的一些数据类型-例如一个电子商务应用程序可以有Users、Products、Orders等模型类。简单来说,模型仅仅是一些域和每个域对应数据的集合。我们将重点研究模型类中的四个主要部分—域(Fields)、代理(Proxies)、关联(Associations)和验证(Validations)。

现在让我们看看如何创建一个模型类:

Ext.define('User', {extend: 'Ext.data.Model',fields: [{ name: 'id', type: 'int' },{ name: 'name', type: 'string' }]
});

模型类通常在存储类中使用,这些存储类主要是一些模型实例的集合。设置存储类和加载它的数据是很简单的:

Ext.create('Ext.data.Store', {model: 'User',proxy: {type: 'ajax',url : 'users.json',reader: 'json'},autoLoad: true
});

我们用Ajax代理( Ajax Proxy)配置我们的存储类,告诉它加载数据的url地址和用来解码数据的读取器(Reader)。这样,我们的服务器将返回JSON格式的数据,我们可以使用设置的Json读取器(Json Reader)来解析响应。上面创建的存储类实例从url地址users.json中自动加载一系列User模型类实例的数据。

users.json应该返回如下所示的JSON字符串:

{success: true,users: [{ id: 1, name: 'Ed' },{ id: 2, name: 'Tommy' }]
}

请查看Simple Store获取一个演示实例。

内联数据

存储类实例也可以加载内联数据,它们转换每个传递进data中的对象为模型类实例:

Ext.create('Ext.data.Store', {model: 'User',data: [{ firstName: 'Ed',    lastName: 'Spencer' },{ firstName: 'Tommy', lastName: 'Maintz' },{ firstName: 'Aaron', lastName: 'Conran' },{ firstName: 'Jamie', lastName: 'Avins' }]
});

内联数据的例子(Inline Data example)

排序和分组

存储类实例能在本地执行排序、过滤和分组,同样也提供远程排序、过滤和分组:

Ext.create('Ext.data.Store', {model: 'User',sorters: ['name', 'id'],filters: {property: 'name',value   : 'Ed'},groupField: 'age',groupDir: 'DESC'
});

我们刚刚创建的存储类实例中,数据首先将按照name排序,其次按id排序;并且数据将被过滤为仅包含name为’Ed’的Users,然后数据将按年龄进行分组且遵循由小到大的顺序。任何时候调用存储类的API进行排序、过滤和分组都是是很轻松的。查看排序、分组、过滤存储类实例(Sorting Grouping Filtering Store)获取一个演示示例。

代理

代理类被存储类使用以便于管理加载和保存模型类数据。有两种类型的代理:客户端代理(Client)和服务器端代理(Server)。客户端代理包括存储数据在浏览器内存的内存方式(Memory)和使用HTML5本地存储器(可用时)的本地存储方式(Local Storage)。服务器端代理操作一些从远程服务器调度来的数据,例如包括Ajax,Jsonp和Rest方式。

代理方式可以直接在模型类中定义,如下:

Ext.define('User', {extend: 'Ext.data.Model',fields: ['id', 'name', 'age', 'gender'],proxy: {type: 'rest',url : 'data/users',reader: {type: 'json',root: 'users'}}
});// Uses the User Model's Proxy
Ext.create('Ext.data.Store', {model: 'User'
});

这对我们有两方面的好处:首先,使得每个使用User模型类的存储类实例以相同方式加载数据变得可行,这样我们避免了必须为每个存储类实例复制相同代理方式的定义。其次,现在我们可以不必使用存储类来加载和保存模型数据:

// Gives us a reference to the User class
// 创建一个User类的引用
var User = Ext.ModelMgr.getModel('User');
var ed = Ext.create('User', {name: 'Ed Spencer',age : 25
});
// We can save Ed directly without having to add him to a Store first because we
//我们可以直接保存ed而不用先把它添加到一个存储类中,因为我们配置了
// configured a RestProxy this will automatically send a POST request to the url /users
//一个能自动发送一个POST请求到指定url的Rest代理
ed.save({success: function(ed) {console.log("Saved Ed! His ID is "+ ed.getId());}
});// Load User 1 and do something with it (performs a GET request to /users/1)
//加载User 1并对其一些相关操作(执行一个GET请求到 /users/1)
User.load(1, {success: function(user) {console.log("Loaded user 1: " + user.get('name'));}
});

也有利用HTML5新功能-- LocalStorage和 SessionStorage – 的代理模式。尽管旧的浏览器不支持这些新的HTML5 APIs,它们仍然是有用的,因为很多应用程序将从这些新特性的存在中受益。

直接在模型类中使用代理的例子(Example of a Model that uses a Proxy directly)

关联

模型类之间可以通过关联API链接在一起。大多数应用程序需要处理很多不同的模型类,并且这些模型类之间通常是相关联的。例如一个博客写作应用程序可能有User(用户)、Post(文章)、Comment(评论)等模型类。每个用户(User)可以创建多篇文章(Posts),并且每篇文章接受很多评论(Comments)。我们可以如下表示这些关系:

Ext.define('User', {extend: 'Ext.data.Model',fields: ['id', 'name'],proxy: {type: 'rest',url : 'data/users',reader: {type: 'json',root: 'users'}},hasMany: 'Post' // shorthand for { model: 'Post', name: 'posts' }
});Ext.define('Post', {extend: 'Ext.data.Model',fields: ['id', 'user_id', 'title', 'body'],proxy: {type: 'rest',url : 'data/posts',reader: {type: 'json',root: 'posts'}},belongsTo: 'User',hasMany: { model: 'Comment', name: 'comments' }
});
Ext.define('Comment', {extend: 'Ext.data.Model',fields: ['id', 'post_id', 'name', 'message'],belongsTo: 'Post'
});

这将使得在你的应用程序中表示这种复杂关系变得简单。 每个模型类可以和其他模型类有任意多的关联,并且你的模型类可以按任意顺序定义。一旦我们创建了一个模型类实例,我们可以很轻松地遍历与其相关联的数据 -- 例如,如果我们想记录一个给定用户的每篇文章的所有相关评论,我们可以如下这样操作:

// Loads User with ID 1 and related posts and comments using User's Proxy
//加载User使用ID 1和相关的文章和评论使用User的代理
User.load(1, {success: function(user) {console.log("User: " + user.get('name'));user.posts().each(function(post) {console.log("Comments for post: " + post.get('title'));post.comments().each(function(comment) {console.log(comment.get('message'));});});}
});

上例我们创建每一个的hasMany关联将产生一个新方法添加到这个模型类上。我们声明的每个User模型类实例有许多(hasMany)文章(Posts),这将为我们添加user.posts()方法,如上面代码段中使用的那样。调用user.posts()方法将返回一个配置了Post模型的存储类实例。依次类推,Post模型实例获取了一个comments()方法,因为我们为其设置了hasMany 评论关联。关联不仅对加载数据来说是有用的,而且对创建新记录也是有用的:

user.posts().add({title: 'Ext JS 4.0 MVC Architecture',body: 'It\'s a great Idea to structure your Ext JS Applications using the built in MVC Architecture...'
});
user.posts().sync();

这里我们实例化了一个新的Post模型类,该实例将自动把User中的id赋值给Post中的user_id字段。调用sync()方法,将通过配置的代理方式来保存新创建的Post模型类实例 – 再者,如果你想让操作完成时得到反馈,你可以调用异步操作并传递进一个回调函数来实现。属于(belongsTo)关联也能在模型类实例中生成一个新方法,如我们下面介绍的这个示例:

// get the user reference from the post's belongsTo association
//得到user实例引用从post实例的belongsTo关联配置
post.getUser(function(user) {console.log('Just got the user reference from the post: ' + user.get('name'))
});
// try to change the post's user
//尝试改变文章的user
post.setUser(100, {callback: function(product, operation) {if (operation.wasSuccessful()) {console.log('Post\'s user was updated');} else {console.log('Post\'s user could not be updated');}}
});

再次说明,加载函数(getUser)是异步调用的,并且需要一个回调函数作为参数来获得user实例。setUser方法仅更新外键(本例中的user_id字段)的值为100,并保存这个Post模型类实例。通常,不管成功与否,当保存操作完成时,传递进去的回调函数都将被触发。

加载内嵌的数据

你或许想知道为什么调用User.load方法时,我们传递一个success方法,但当访问User的文章(Post)及评论(Comment)时我们并不需要这样做。这是因为上面的例子中,我们假定当发送请求以获取一个用户的信息时,服务器返回了该用户的数据及所有嵌套的文章和评论的数据。上例我们通过设置关联配置,框架在一次请求中就能自动解析出嵌套的数据。不是靠先发送一个请求获取用户数据,另一个请求获取文章数据,再发送其他请求以获取每篇文章的评论数据这种模式,我们可以在一次服务器响应中返回所有的数据,如下:

{success: true,users: [{id: 1,name: 'Ed',age: 25,gender: 'male',posts: [{id   : 12,title: 'All about data in Ext JS 4',body : 'One areas that has seen the most improvement...',comments: [{id: 123,name: 'S Jobs',message: 'One more thing'}]}]}]
}

这些数据将被框架自动解析出来。配置模型类的代理方式以用来加载任何地方的数据会变得很轻松,并且它们的阅读器模式几乎可以处理任何格式的响应数据。和Ext JS 3一样,模型类和存储类在整个框架中被许多组件使用,例如表格,树,表单。

查看关联和验证(Associations and Validations)的演示示例以获取一个可实际操作并且具有关联关系的模型实例。

当然,你可以以一种非嵌套的方式加载你的数据。如果你仅想需要时加载相关的数据,这种“懒惰加载”模式将可能是有效地。如前所做,我们仅加载User数据,除此之外,我们假定返回的响应仅包含User数据,没有任何相关联的文章(Post)数据。然后,我们在user.posts().load()方法添加回调函数中以获取相关的文章(Post)数据:

// Loads User with ID 1 User's Proxy
User.load(1, {success: function(user) {console.log("User: " + user.get('name'));// Loads posts for user 1 using Post's Proxyuser.posts().load({callback: function(posts, operation) {Ext.each(posts, function(post) {console.log("Comments for post: " + post.get('title'));post.comments().each(function(comment) {console.log(comment.get('message'));});});}});}
});

查看懒惰关联(Lazy Associations)模式可以获取一个完整的示例

验证

自Ext JS 4起,模型类由于提供了验证数据的功能而变得更加丰富精彩了。为了证明这点,我们将在前面使用过的关联例子的基础上构建一个示例。首先让我们添加一些验证到User模型类中:

Ext.define('User', {extend: 'Ext.data.Model',fields: ...,validations: [{type: 'presence', name: 'name'},{type: 'length',   name: 'name', min: 5},{type: 'format',   name: 'age', matcher: /\d+/},{type: 'inclusion', name: 'gender', list: ['male', 'female']},{type: 'exclusion', name: 'name', list: ['admin']}],proxy: ...
});

验证和域定义遵循相同的代码格式。任何情况下,我们都可以指定一个域和一种验证类型。我们例子中的验证器配置要求name域必须存在,并且至少5个字符长,age域必须为数字,gender域的值只能为male或female,并且用户名可以为除了admin外的其他任何名称。一些验证器可能具有其他的可选配置 -- 例如,长度验证可以具有最大和最小属性,格式(format)可以具有匹配(matcher)属性等。Ext JS有五种内置的验证器,且可以轻松地添加用户自定义规则。首先让我们看看这五种类型:

  • 存在(presence)  确保该域必须有确定值。0被看作有效值,但空字符串将不被视为有效值。
  • 长度(length)  确保一个字符串长度位于最大和最小值之间。两个参数都是可选的。
  • 格式(format)  确保一个字符串匹配指定的正则表达式。上例中我们确保age域必须为数字。
  • 包含(inclusion) 确保该域的值在指定的数值集合中(例如确保性别只能是男或女)。
  • 排除(exclusion) 确保该域的值不在指定的数值集合中(例如用户名不能为admin)

既然我们已经理解了不同验证器的功能,让我们尝试在一个User实例中使用它们。

我们创建一个user实例并在其中运行验证器,注意产生的任何错误:

// now lets try to create a new user with as many validation errors as we can
// 现在让我们尝试创建一个user实例,并产生尽量多的验证错误
var newUser = Ext.create('User', {name: 'admin',age: 'twenty-nine',gender: 'not a valid gender'
});
// run some validation on the new user we just created
// 在我们刚刚创建的user实例中运行一些验证器
var errors = newUser.validate();
console.log('Is User valid?', errors.isValid()); //returns 'false' as there were validation errors 当有验证器错误产生时,返回false
console.log('All Errors:', errors.items); //returns the array of all errors found on this model instance返回该模型类实例所有错误组合成的数组
console.log('Age Errors:', errors.getByField('age')); //returns the errors for the age field返回age域产生的错误

这里的关键函数是validate(),该函数运行所有配置验证器并返回一个Errors对象。这个简单的对象为所有错误的集合,并且添加了一些便利的方法,例如isValid() -- 当任何域都没有错误产生时,返回true,还有getByField()方法,返回给定域产生的所有错误。

请查看关联和验证(Associations and Validations)示例以获取一个使用验证器的复杂例子。

转载于:https://my.oschina.net/yoyoko/blog/130966

ExtJS4 API文档阅读(四)——Data相关推荐

  1. 聚合API文档阅读帮助

    聚合API文档阅读帮助 该文基于聚合云数据开放平台的API文档,目的使得开发者能够方便的快速了解我们这个API文档的结构,从而能够经行高效的开发. 该API文档总共有6个大类:国外API.国内API. ...

  2. Django QuerySet API 文档阅读(3):QuerySet定义(一)

    原文地址:​​​​​​QuerySet API reference | Django documentation | Django QuerySet有两个属性,ordered和db: ordered: ...

  3. Zeal —— API文档离线阅读器

    背景 在软件开发的过程中,常常需要查阅多个API文档,但网络环境等因素常常导致在线文档查看用户体验并不佳.为此,介绍一款离线的API文档阅读器,Zeal.Zeal中自配了多种API文档可供查阅,如El ...

  4. 什么是API? [如何编写和阅读API文档]

    随着API在互联网时代中变得越来越普遍,不仅是编程人员会用到,现在也会要求产品经理或互联网运营会调试和对接API.看这篇文章的你可能会使用或开发API,或者两者兼而有之. 因此,对你来说,不仅要了解如 ...

  5. Splinter入门(十四)API文档

    Splinter入门(十四)API文档 1. Browser 2. DriverAPI 3. ElementAPI 4. CookieManager 5. ElementList 6. Request ...

  6. layer.js 弹窗组件API文档

    基础参数 type title content skin area offset icon btn closeBtn shade shadeClose time id shift maxmin fix ...

  7. 转: HighCharts 详细使用及API文档说明

    一.HighCharts开发说明: HighCharts开发实际上配置HighCharts每个部分,比如配置标题(title),副标题(subtitle)等,其中每个部分又有更细的参数配置,比如标题下 ...

  8. Spring Boot 2.x基础教程:使用Swagger2构建强大的API文档

    点击蓝色"程序猿DD"关注我 回复"资源"获取独家整理的学习资料! 作者 | 翟永超 来源 | didispace.com/spring-boot-learni ...

  9. Spring Boot 集成 Swagger 生成 RESTful API 文档

    原文链接: Spring Boot 集成 Swagger 生成 RESTful API 文档 简介 Swagger 官网是这么描述它的:The Best APIs are Built with Swa ...

最新文章

  1. Vue轮播图插件---Vue-Awesome-Swiper
  2. 2020年什么名字最受欢迎?前面“奕辰”你别走
  3. 寒假集训【1.26】
  4. Mysql编码教程_mysql编码设置教程 mysql编码要怎么设置呢
  5. Linux 查看内存状态
  6. DSP关于存储器读写、IO读写时序图的注意点
  7. vestacp升级php,升级VestaCP面板PHP版本至PHP7.x
  8. IDM磁力解析 IDM磁力使用教程
  9. 机器人(机械臂)动力学建模方法(Euler-Lagrange equation)
  10. Matlab计算熵权法
  11. 【保姆级教学】Landsat遥感影像下载
  12. Android自定义带搜索图标及删除按钮的搜索框SearchEditText
  13. Autovue Client/Server 部署时的连接问题及诊断策略
  14. 为什么走线选择50欧姆阻抗
  15. Debian查看系统版本信息
  16. Redis的集群配置
  17. python柱状图zzt_Python torch.diag方法代碼示例
  18. lucene 中文 完全匹配不是top1
  19. 事务的隔离 transaction isolation
  20. WannaCry勒索病毒,企业文件安全保护的启蒙课

热门文章

  1. python多态_多态是什么?为什么要使用多态?
  2. 2sin30°在python中如何表示_如何在python中实现以下派生公式?
  3. java调用keras theano模型_使用Keras / Theano和LSTM进行多标签文本分类
  4. java 桥接模式_JAVA设计模式之【桥接模式】
  5. editor修改样式 vue_手摸手Electron + Vue实战教程(三)
  6. python 拓扑排序 dfs bfs_bfs与dfs的优缺点?
  7. 逻辑漏洞之密码找回总结
  8. IIS请求筛选模块被配置为拒绝超过请求内容长度的请求
  9. springmvc使用freemarker
  10. 数据结构(一)---顺序表的实现---java版