- Ember.js 指南
- 入门指南 - 介绍
- 入门指南 - 应用规划
- 入门指南 - 创建静态页面
- 入门指南 - 获取Ember.js和相应依赖
- 入门指南 - 添加第一个路由与模板
- 入门指南 - 建立模型
- 入门指南 - 使用静态数据
- 入门指南 - 显示模型数据
- 入门指南 - 显示模型的完成状态
- 入门指南 - 创建新的模型实例
- 入门指南 - 标记模型为完成或未完成
- 入门指南 - 显示未完成待办事项的数量
- 入门指南 - 切换显示和编辑状态
- 入门指南 - 接受修改
- 入门指南 - 删除模型
- 入门指南 - 添加子路由
- 入门指南 - 显示未完成待办事项
- 入门指南 - 显示已完成待办事项
- 入门指南 - 显示所有待办事项
- 入门指南 - 添加移除所有已完成待办事项的按钮
- 入门指南 - 提示所有待办事项已完成
- 入门指南 - 切换已完成和未完成待办事项
- 入门指南 - 更换FixtureAdapter
- 获取 Ember - 获取Ember
- 概念 - 核心概念
- 概念 - 命名惯例
- 对象模型 - 类与实例
- 对象模型 - 计算属性
- 对象模型 - 计算属性和带@each的集合数据
- 对象模型 - 观察器
- 对象模型 - 绑定
- 对象模型 - 重新打开类和实例
- 对象模型 - 绑定,观察器,计算属性:如何选择?
- 应用 - 介绍
- 模板 - 应用模板
- 模板 - Handlebars基础
- 模板 - 条件表达式
- 模板 - 显示项目列表
- 模板 - 切换作用域
- 模板 - 绑定元素属性
- 模板 - 绑定元素类名称
- 模板 - 链接
- 模板 - 操作
- 模板 - 输入助手
- 模板 - 开发助手
- 模板 - 用助手来渲染
- 模板 - 编写助手方法
- 路由 - 介绍
- 路由 - 定义路由
- 路由 - 生成的对象
- 路由 - 指定路由的模型
- 路由 - 设置控制器
- 路由 - 渲染模板
- 路由 - 重定向
- 路由 - 指定地址API
- 路由 - 查询参数
- 路由 - 异步路由
- 路由 - 加载中/错误子状态
- 路由 - 阻止和重试过渡
- 组件 - 介绍
- 组件 - 定义组件
- 组件 - 传递属性
- 组件 - 包裹内容
- 组件 - 自定义组件元素
- 组件 - 使用Action处理用户交互
- 组件 - 从组件发送操作给应用
- 控制器 - 介绍
- 控制器 - 代表单一模型
- 控制器 - 代表多模型
- 控制器 - 管理控制器间的依赖
- 模型 - 介绍
- 模型 - 定义模型
- 模型 - 创建和删除记录
- 模型 - 将记录推入仓库
- 模型 - 持久化记录
- 模型 - 查询记录
- 模型 - 使用记录
- 模型 - 使用Fixture
- 模型 - 连接HTTP服务器
- 模型 - 处理元数据
- 模型 - 自定义适配器
- 模型 - 常见问题
- 视图 - 介绍
- 视图 - 定义视图
- 视图 - 处理事件
- 视图 - 在模板中插入视图
- 视图 - 为视图添加布局
- 视图 - 自定义视图元素
- 视图 - 内置视图
- 视图 - 手动管理视图层级
- 枚举 - 介绍
- 测试 - 介绍
- 测试 - 集成测试
- 测试 - 测试助手
- 测试 - 测试用户交互
- 测试 - 单元测试
- 测试 - 单元测试基础
- 测试 - 测试组件
- 测试 - 测试控制器
- 测试 - 测试路由
- 测试 - 测试模型
- 测试 - 自动化测试
- 配置Ember.js - 禁用基本类型扩展
- 配置Ember.js - 嵌入式应用
- 配置Ember.js - 特性标识
- Cookbook - 简介
- Cookbook - 用户界面与交互
- Cookbook - 事件处理和数据绑定
- Cookbook - 助手与组件
- Cookbook - 使用对象
- 理解Ember.js - 视图层
- 理解Ember.js - 管理异步
- 理解Ember.js - 模板自动更新
- 理解Ember.js - 调试
- 理解Ember.js - 运行循环
模型 - 常见问题
英文原文:http://emberjs.com/guides/models/frequently-asked-questions/
应该使用查询还是过滤条件来查询记录?
这取决于想要查询多少记录和记录是否已经加载到仓库。
查询比较适合于搜索成百上千甚至百万级的记录。需要做的只是将搜索条件发送给服务器端,然后搜索匹配的记录的责任就交由服务器来处理。因为服务器返回的数据包含匹配的记录的ID,所以仓库即使之前没有加载这些记录也不会有影响;仓库发现这些记录并没有被缓存会通过ID来发送请求获取记录。
使用查询的缺点是它们无法得到自动更新,效率较低,并且要求服务器端支持希望执行的查询类型。
因为服务器端决定与查询匹配的记录,而不是仓库,查询无法自动更新。如果需要更新查询结果,需要手动的调用reload()
,并等待服务器端返回。如果在客户端创建了一个新的记录,该记录不会自动在结果中显示,除非服务端已经包含了该记录,并且重新加载了查询结果。
因为仓库必须让服务器端来决定查询的结果,因此需要一个网络请求。这会让用户觉得缓慢,特别是在用于与服务器间的连接速度较慢的情况下。当需要访问服务器的话,Javascript Web应用会明显的感觉到慢。
最后,执行查询需要仓库和服务器端协同工作。在默认情况下,Ember Data将搜索条件作为HTTP请求的body
发送到服务器端。如果服务器端并不支持查询的格式,那么需要修改服务器以便支持查询,或者通过自定义一个适配器来定义需要发送的查询。
过滤器是对仓库中缓存的对象执行实时的查询。一旦新的记录被加载到仓库,过滤器会自动检查记录是否匹配条件,如果匹配,会将其加入到搜索结果的数组中。如果这个数组显示在模板中,模板也会自动更新。
过滤器还会顾及新创建的还未保存的记录,以及被修改未保存的记录。如果希望记录在客户端一创建或者修改就在搜索结果中显示,那么就应该是用过滤器。
请记住,如果仓库不知道记录的存在,记录不会包含在过滤器中。通过仓库的push()
方法可以确保仓库知道记录的存在。
此外也有一个制约条件,就是有多少记录可以保存在内存中进行过滤,直到出现性能问题。
最后,应该联合使用查询和过滤器来扬长避短。记住通过查询服务器返回的记录都是缓存在仓库中的。可以利用这一点来做过滤,通过查询仓库来将记录加载到仓库,然后使用一个过滤函数来匹配相同的记录。
这可以避免所有的记录都通过服务器来查询,同时也创建了一个能包含客户端创建和修改的记录的动态更新列表。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | App.PostsFavoritedRoute = Ember.Route.extend({ model: function() { var store = this.store; // Create a filter for all favorited posts that will be displayed in // the template. Any favorited posts that are already in the store // will be displayed immediately; // Kick off a query to the server for all posts that // the user has favorited. As results from the query are // returned from the server, they will also begin to appear. return store.filter('post', { favorited: true }, function(post) { return post.get('isFavorited'); }); } }); |
如何将后台创建的记录通知Ember Data
当通过Ember Data的store.find
方法来请求一条记录时,Ember会自动将数据加载到store
中。这样Ember就避免了在之后在发起一个请求来获取已经获取到的记录。此外,加载一条记录到store
时,所有的包含该条记录的RecordArray
都会被更新(例如store.filter
或者store.all
构造的)。这就意味着所有依赖与RecordArray
的数据绑定或者计算属性都会在添加新的或者更新记录值的时候自动进行同步。
而一些应用可能希望能不通过store.find
请求记录来添加或者更新store
中得记录。为了实现这种需求,可以通过使用DS.Store
的push
,pushPayload
,或者update
方法。这对于那些有一个通道(例如SSE或者Web Socket)通知应用后台有新记录创建或者更新非常有用。
push是加载记录到Ember Data的store
的最简单方法。当使用push
时,一定要记住将JSON对象推入store
之前将其反序列化。push
一次只接受一条记录。如果希望一次加载一组记录到store
那么可以调用pushMany.
1 2 3 4 5 6 | socket.on('message', function (message) { var type = store.modelFor(message.model); var serializer = store.serializerFor(type.typeKey); var record = serializer.extractSingle(store, type, message.data); store.push(message.model, record); }); |
pushPayload是一个store#push
方法的便利封装,它将使用模型实现了pushPayload
方法的序列化对象来反序列化有效载荷。需要注意的是这个方法并不能与JSONSerializer
一同使用,因为其并没有实现pushPayload
方法。
1 2 3 | socket.on('message', function (message) { store.pushPayload(message.model, message.data); }); |
update与push
方法类似,不同的是其可以处理部分属性,而不需要覆盖整个记录的属性。这个方法对于只接收到记录改变的属性的通知的应用尤为有用。与push
方法一样,update
需要在调用之前将JSON对象反序列化。
1 2 3 4 5 6 7 8 9 10 11 12 | socket.on('message', function (message) { var hash = message.data; var type = store.modelFor(message.model); var fields = Ember.get(type, 'fields'); fields.forEach(function(field) { var payloadField = Ember.String.underscore(field); if (field === payloadField) { return; } hash[field] = hash[payloadField]; delete hash[payloadField]; }); store.push(message.model, hash); }); |
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论