×

EmberJS 教程

EmberJS 概述EmberJS 环境配置EmberJS 应用EmberJS 对象模型EmberJS 模板EmberJS 路由器EmberJS 组件EmberJS 模型EmberJS 视图EmberJS 控制器EmberJS 测试EmberJS 指定查询参数

Ember 对象模型

Ember 类的定义 初始化 继承Ember 类的扩展Ember 计算属性Ember 观察者Ember 数据绑定Ember 枚举Ember 第一章对象模型小结

Ember handlebars模板

Ember handlebars基础Ember handlebars条件表达式Ember handlebars遍历标签Ember handlebars显示对象键Ember handlebars属性绑定Ember {{link-to}} 助手Ember 路由 模板执行渲染顺序Ember {{action}} 助手Ember 表单元素Ember 调试助手Ember 工具类的助手Ember 第二章模板小结

Ember 路由

Ember 路由定义Ember 指定与路由关联的模型Ember 模板渲染Ember 路由重定向Ember 路由终止挑战和激活Ember loading error子路由Ember 查询参数Ember 异步路由

Ember 组件

Ember 组件定义Ember 属性传递Ember 包裹内容自定义包裹组件的HTML标签Ember 处理事件Ember action触发变化

Ember 控制器

Ember 控制器Ember 管理控制器的依赖关系

Ember 模型

Ember model简介Ember 定义模型Ember 记录查询Ember 新建、更新、删除记录Ember 设置记录到StoreEmber model的关联关系处理Ember 元数据Ember 自定义适配器Ember 自定义序列号器

Ember 测试

Ember 测试简介Ember 验收测试Ember 单元测试

Ember 定义模型


模型也是一个类,它定义了向用户展示的属性和数据行为。模型的定义非常简单,只需要继承DS.Model类即可,或者你也可以直接使用Ember CLI命令创建。比如使用命令模型 ember g model person定义了一个模型类person

//  app/models/person.js

import DS from 'ember-data';

export default DS.Model.extend({

});

这个是个空的模型,没有定义任何属性。有了模型类你就可以使用find方法查找数据了。

1,定义属性

上面定义的模型类person还没有任何属性,下面为这个类添加几个属性。

//  app/models/person.js

import DS from 'ember-data';

export default DS.Model.extend({
    firstName: DS.attr(),
    lastName: DS.attr(),
    birthday: DS.attr()  
});

上述代码定义了3个属性,但是还未给属性指定类型,默认都是string类型。这些属性名与你连接的服务器上的数据key是一致的。甚至你还可以在模型中定义计算属性

//  app/models/person.js

import DS from 'ember-data';

export default DS.Model.extend({
    firstName: DS.attr(),
    lastName: DS.attr(),
    birthday: DS.attr(),

    fullName: Ember.computed('firstName', 'lastName', function() {
        return `${this.get('firstName')} ${this.get('lastName')}`;
    })
});

这段代码在模型类中定义了一个计算属性fullName

2,指定属性类型与默认值

前面定义的模型类是没有指定属性类型的,默认情况下都是string类型,显然这是不够的,简单的模型属性类型包括:stringnumberbooleandate。这几个类型我想不用我解释都应该知道了。

不仅可以指定属性类型,你还可以指定属性的默认值,在attr()方法的第二个参数指定。比如下面的代码:

//  app/models/person.js

import DS from 'ember-data';

export default DS.Model.extend({
    username: DS.attr('string'),
    email: DS.attr('string'),
    verified: DS.attr('boolean', { defaultValue: false }),  //指定默认值是false
    //  使用函数返回值作为默认值
    createAt: DS.attr('string', { defaultValue(){ return new Date(); } })
});

正如代码注释所述的,设置默认值的方式包括直接指定或者是使用函数返回值指定。

3,定义模型的关联关系

Ember 的模型也是有类似于数据库的关联关系的。只是相对于复制的数据库 Ember 的模型就显得简单很多,其中包括一对一,一对多,多对多关联关系。这种关系是与后台的数据库是相统一的。

1,一对一

声明一对一关联使用 DS.belongsTo 设置。比如下面的两个模型。

//  app/models/user.js
import DS from 'ember-data';

export default DS.Model.extend({
  profile: DS.belongsTo(‘profile’);
});
//  app/models/profile.js
import DS from ‘ember-data’;
export default DS.Model.extend({
  user: DS.belongsTo(‘user’);
});

2,一对多

声明一对多关联使用 DS.belongsTo (多的一方使用)和 DS.hasMany (少的一方使用)设置。比如下面的两个模型。

//  app/models/post.js
import DS from ‘ember-data’;
export default DS.Model.extend({
  comments: DS.hasMany(‘comment’);
});

这个模型是一的一方。下面的模型是多的一方;

//  app/models/comment.js
import DS from ‘ember-data’;
export default DS.Model.extend({
  post: DS.belongsTo(‘post’);
});

这种设置的方式与Java 的hibernate非常相似。

3,多对多

声明一对多关联使用 DS.hasMany 设置。比如下面的两个模型。

//  app/models/post.js
import DS from ‘ember-data’;
export default DS.Model.extend({
  tags: DS.hasMany(‘tag’);
});
//  app/model/tag.js
import DS from ‘ember-data’;
export default DS.Model.extend({
  post: DS.hasMany(‘post’);
});

多对多的关系设置都是使用 DS.hasMany ,但是并不需要“中间表”,这个与数据的多对多有点不同,如果是数据的多对多通常是通过中间表关联。

4,显式反转

Ember Data会尽力去发现两个模型之间的关联关系,比如前面的一对多关系中,当comment发生变化的时候会自动更新到post,因为每一个comment只对应一个post,可以有comment确定到某个一个post

然而,有时候同一个模型中会有多个与此关联模型。这时你可以在反向端用 DS.hasMany 的inverse选项指定其关联的模型:

//  app/model/comment.js
import DS from 'ember-data';
export default DS.Model.extend({
  onePost: DS.belongsTo(‘post’),
  twoPost: DS.belongsTo(‘post’),
  redPost: DS.belongsTo(‘post’),
  bluePost: DS.belongsTo(‘post’)
});

在一个模型中同时与3个post关联了。

//  app/models/post.js
import DS from ‘ember-data’;
export default DS.Model.extend({
  comments: hasMany(‘comment’, { inverse: ‘redPost’ });
});

comment发生变化时自动更新到redPost这个模型。

5,自反关系

1,一对多

当你想定义一个自反关系的模型时(模型本身的一对一关系),你必须要显式使用inverse指定关联的模型。如果没有逆向关系则把inverse值设置为null

//  app/models/folder.js
import DS from ‘ember-data’;
export default DS.Model.extend({
  children: DS.hasMany(‘folder’, { reverse: ‘parent’ });
  parent: DS.hasMany(‘folder’, { reverse: ‘children’ });
});

一个文件夹通常有父文件夹或者子文件夹。此时父文件夹和子文件夹与本身都是同一个类型的模型。此时你需要显式使用inverse属性指定,比如这段代码所示,“children……”这行代码意思是这个模型有一个属性children,并且这个属性也是一个folder,模型本身作为父文件夹。同理“parent……”这行代码的意思是这个模型有个属性parent,并且这个属性也是一个folder,模型本身是这个属性的子文件夹。比如下图结构:

结构图

这个有点像数据结构中的链表。你可以把childrenparent想象成是一个指针。

如果仅有关联关系没有逆向关系直接把inverse设置为null

//  app/models/folder.js
import DS from ‘ember-data’;
export default DS.Model.extend({
  parent: DS.belongsTo(‘folder’, { inverse: null });
});

2,一对一

//  app/models/user.js
import DS from ‘ember-data’;
export default DS.Model.extend({
  bestFriend: DS.belongsTo(‘folder’, { inverse: ‘bestFriend’ });
});v

这个关系与数据库设置设计中双向一对一很类似。

6,嵌套数据

有些模型可能会包含深层嵌套的数据对象,如果也是使用上述的关联关系定义那么将是个噩梦!对于这种情况最好是把数据定义成简单对象,虽然增加点冗余数据但是降低了层次。另外一种是把嵌套的数据定义成模型的属性(也是增加冗余但是降低了嵌套层次)。


分类导航

关注微信下载离线手册

bootwiki移动版 bootwiki
(群号:472910771)