28、Ember Data 模型与数据绑定实战指南

Ember Data 模型与数据绑定实战指南

在开发应用程序时,数据层的处理至关重要。本文将深入介绍如何使用 Ember Data 来定义模型、创建记录、使用 get set 方法,以及如何处理计算属性。同时,还会探讨数据的检索、保存和销毁操作。

1. 引入 Ember Data

在 Tracker 应用中,我们将从数据层入手,使用模型来管理数据。Ember 提供了 Ember.Object 类来定义应用的数据架构,但对于现代应用来说,还需要更多功能。Ember Data 是一个基于 Ember.Object 的 JavaScript 库,它可以帮助我们添加特定于模型的功能,抽象处理各种数据源(如 RESTful API、localStorage 和静态固定数据)的复杂性,并提供一个内存数据存储,用于创建、检索、更新和删除模型实例。

2. 模型定义

Ember CLI 已经加载了 Ember Data 库,我们可以开始构建模型。使用 ember g model [model name] 命令创建所需的模型文件:

ember g model cryptid
ember g model sighting
ember g model witness
2.1 Cryptid 模型

打开 app/models/cryptid.js 文件,添加以下属性:

import DS from 'ember-data';
export default DS.Model.extend({
  name: DS.attr('string'),
  cryptidType: DS.attr('string'),
  profileImg: DS.attr('string'),
  sightings: DS.hasMany('sighting')
});

DS.attr 方法用于指定模型属性,可设置属性类型和默认值。 DS.hasMany 用于定义多对多关系,当查询 RESTful API 中的 cryptid 时,会返回关联的 sighting 实例数组。

2.2 Witness 模型

打开 app/models/witness.js 文件,添加以下属性:

import DS from 'ember-data';
export default DS.Model.extend({
  fName: DS.attr('string'),
  lName: DS.attr('string'),
  email: DS.attr('string'),
  sightings: DS.hasMany('sighting')
});
2.3 Sighting 模型

打开 app/models/sighting.js 文件,添加以下属性:

import DS from 'ember-data';
export default DS.Model.extend({
  location: DS.attr('string'),
  createdAt: DS.attr('date'),
  sightedAt: DS.attr('date'),
  cryptid: DS.belongsTo('cryptid'),
  witnesses: DS.hasMany('witness')
});

DS.belongsTo 用于定义一对多关系,每个 cryptid 可以有多个 sighting 实例。

3. 创建记录

应用初始化时,Ember Data 会创建一个本地存储对象 this.store ,用于创建、检索、更新和删除模型记录。使用 this.store.createRecord 方法创建记录,例如在 app/routes/sightings.js 中:

import Ember from 'ember';
export default Ember.Route.extend({
  model() {
    let record1 = this.store.createRecord('sighting', {
      location: 'Atlanta',
      sightedAt: new Date('2016-02-09')
    });
    let record2 = this.store.createRecord('sighting', {
      location: 'Calloway',
      sightedAt: new Date('2016-03-14')
    });
    let record3 = this.store.createRecord('sighting', {
      location: 'Asilomar',
      sightedAt: new Date('2016-03-21')
    });
    return [record1, record2, record3];
  }
});

运行 ember server ,访问 http://localhost:4200/sightings 查看新记录。

4. get 和 set 方法

Ember Data 模型记录的核心是 Ember.Object ,它包含 get set 方法。 get 方法用于获取属性值, set 方法用于设置属性值。例如在 app/routes/sightings.js 中:

import Ember from 'ember';
export default Ember.Route.extend({
  model() {
    let record1 = this.store.createRecord('sighting', {
      location: 'Atlanta',
      sightedAt: new Date('2016-02-09')
    });
    console.log("Record 1 location: " + record1.get('location'));
    record1.set('location', 'Paris, France');
    console.log("Record 1 location: " + record1.get('location'));
    return [record1, record2, record3];
  }
});

重新加载浏览器,在控制台查看属性值的变化。

5. 计算属性

计算属性在管理模板和组件的模型属性中非常重要。 Ember.computed 方法可以监听属性变化并返回一个值。例如,在 app/models/witness.js 中添加一个计算属性 fullName

import DS from 'ember-data';
export default DS.Model.extend({
  fName: DS.attr('string'),
  lName: DS.attr('string'),
  email: DS.attr('string'),
  sightings: DS.hasMany('sighting'),
  fullName:  Ember.computed('fName', 'lName', function(){
    return this.get('fName') + ' ' + this.get('lName');
  })
});

app/routes/witnesses.js 中创建一个新的 witness 记录并测试计算属性:

import Ember from 'ember';
export default Ember.Route.extend({
  model() {
    let witnessRecord = this.store.createRecord('witness', {
      fName: "Todd",
      lName: "Gandee",
      email: "fake@bignerdranch.com"
    });
    return [witnessRecord];
  }
});

编辑 app/templates/witnesses.hbs 文件以显示 witness 数据:

{{outlet}}
<h1>Witnesses</h1>
<div class="row">
  {{#each model as |witness|}}
    <div class="col-xs-12 col-sm-6 col-md-4">
      <div class="well">
        <div class="thumbnail">
          <div class="caption">
            <h3>{{witness.fullName}}</h3>
            <div class="panel panel-danger">
              <div class="panel-heading">Sightings</div>
            </div>
          </div>
        </div>
      </div>
    </div>
  {{/each}}
</div>

访问 http://localhost:4200/witnesses 查看结果。

6. 数据检索方法

Ember Data 的存储对象提供了多种数据检索方法,如下表所示:
| 请求类型 | 检索所有记录 | 检索单个记录 |
| — | — | — |
| 查找持久化和本地记录 | findAll | findRecord |
| 仅查找本地记录 | peekAll | peekRecord |
| 查找过滤记录 | query | queryRecord |

  • findAll :只需提供模型名称,如 findAll('witness')
  • findRecord :除模型名称外,还需提供记录的标识符,如 findRecord('witness', 5)
  • peekAll peekRecord :与上述方法参数相同,但会立即返回数据,而不是返回 Promise。
  • query queryRecord :适用于 API 支持查询参数的情况,可根据键值对过滤记录。
7. 数据保存和销毁

更新(保存)和销毁记录是创建和检索数据后的后续操作。使用 modelRecord.save 方法保存数据,根据记录状态发送 POST 或 PUT 请求。使用 modelRecord.destroyRecord 方法销毁记录,发送 DELETE 请求并从内存中移除记录。

8. 挑战任务
  • 青铜挑战 :将 witness 模型中的 fullName 计算属性绑定的属性改为 email fName ,显示为 Todd - tgandee@bignerdranch.com
  • 白银挑战 :为 sighting 模型添加一个布尔属性 isNew ,默认值为 false ,将其中一个创建的记录的 isNew 属性设置为 true ,使用 Ember Inspector 查看数据。
  • 黄金挑战 :为 witness 模型添加一个 title 属性,设置默认值,除一个记录外,为其他记录设置不同的标题,添加一个计算属性 titleName 显示标题和姓名。

通过以上步骤,我们可以使用 Ember Data 有效地管理应用程序的数据层,实现模型的定义、记录的创建和操作,以及数据的检索、保存和销毁。同时,计算属性的使用可以方便地处理数据的格式化和展示。希望这些内容能帮助你更好地理解和应用 Ember Data。

Ember Data 模型与数据绑定实战指南

9. 详细解析数据检索方法

在实际应用中,不同的数据检索方法有着不同的使用场景和特点。下面我们详细解析一下这些方法。

9.1 findAll 方法

findAll 方法用于检索指定模型的所有记录。它只需要一个参数,即模型名称。例如,要获取所有的 witness 记录,可以使用以下代码:

this.store.findAll('witness').then((witnesses) => {
  // 处理返回的 witnesses 数据
  console.log(witnesses);
});

当调用 findAll('witness') 时,Ember Data 会构建一个 Ajax 请求,请求的 URL 为 /witnesses/ 。需要注意的是,虽然传入的是模型的单数名称,但 Ember Data 会自动将其转换为复数形式用于构建 URL。

9.2 findRecord 方法

findRecord 方法用于检索指定模型的单个记录。除了模型名称外,还需要提供记录的标识符,通常是记录的 id 。例如,要获取 id 为 5 的 witness 记录,可以使用以下代码:

this.store.findRecord('witness', 5).then((witness) => {
  // 处理返回的 witness 数据
  console.log(witness);
});

调用 findRecord('witness', 5) 时,会创建一个请求,请求的 URL 为 /witnesses/5

9.3 peekAll 和 peekRecord 方法

peekAll peekRecord 方法与 findAll findRecord 类似,但它们只在本地存储中查找数据,不会向服务器发送请求。这两个方法会立即返回数据,而不是返回一个 Promise。例如:

let allWitnesses = this.store.peekAll('witness');
let singleWitness = this.store.peekRecord('witness', 5);
console.log(allWitnesses);
console.log(singleWitness);
9.4 query 和 queryRecord 方法

如果你的 API 支持查询参数,那么 query queryRecord 方法会非常有用。这两个方法的第一个参数是模型名称,最后一个参数是查询对象,其键值对会被转换为查询字符串的值。例如:

this.store.query('user', { fName: "todd" }).then((users) => {
  // 处理返回的 users 数据
  console.log(users);
});

this.store.queryRecord('user', { email: 'me@test.com' }).then((user) => {
  // 处理返回的 user 数据
  console.log(user);
});

调用 query('user', { fName: "todd" }) 会生成一个请求 /users/?f_name=todd ,而 queryRecord('user', { email: 'me@test.com' }) 会生成一个请求 /users?email=me@test.com

10. 数据保存和销毁的深入理解

数据的保存和销毁操作是数据管理中的重要环节,下面我们深入理解一下这两个操作。

10.1 数据保存

当我们使用 set 方法修改了模型记录的属性值后,需要调用 modelRecord.save 方法将这些更改保存到服务器。 save 方法会根据记录的状态发送 POST 或 PUT 请求。如果记录是新创建的,还未保存到服务器,会发送 POST 请求;如果记录已经存在于服务器,会发送 PUT 请求。例如:

let witness = this.store.createRecord('witness', {
  fName: "John",
  lName: "Doe",
  email: "john.doe@example.com"
});

witness.set('fName', 'Jane');
witness.save().then(() => {
  console.log('Witness saved successfully');
}).catch((error) => {
  console.error('Error saving witness:', error);
});
10.2 数据销毁

使用 modelRecord.destroyRecord 方法可以销毁一个记录。这个方法会发送一个 DELETE 请求到服务器,并从本地存储中移除该记录。例如:

let witnessToDelete = this.store.findRecord('witness', 5).then((witness) => {
  witness.destroyRecord().then(() => {
    console.log('Witness deleted successfully');
  }).catch((error) => {
    console.error('Error deleting witness:', error);
  });
});
11. 挑战任务实现思路
11.1 青铜挑战

要将 witness 模型中的 fullName 计算属性绑定的属性改为 email fName ,可以修改 app/models/witness.js 文件:

import DS from 'ember-data';
export default DS.Model.extend({
  fName: DS.attr('string'),
  lName: DS.attr('string'),
  email: DS.attr('string'),
  sightings: DS.hasMany('sighting'),
  fullName:  Ember.computed('fName', 'email', function(){
    return this.get('fName') + ' - ' + this.get('email');
  })
});
11.2 白银挑战

sighting 模型添加 isNew 属性,并设置默认值为 false 。在 app/models/sighting.js 文件中添加以下代码:

import DS from 'ember-data';
export default DS.Model.extend({
  location: DS.attr('string'),
  createdAt: DS.attr('date'),
  sightedAt: DS.attr('date'),
  cryptid: DS.belongsTo('cryptid'),
  witnesses: DS.hasMany('witness'),
  isNew: DS.attr('boolean', { defaultValue: false })
});

然后在创建记录时,将其中一个记录的 isNew 属性设置为 true

import Ember from 'ember';
export default Ember.Route.extend({
  model() {
    let record1 = this.store.createRecord('sighting', {
      location: 'Atlanta',
      sightedAt: new Date('2016-02-09'),
      isNew: true
    });
    let record2 = this.store.createRecord('sighting', {
      location: 'Calloway',
      sightedAt: new Date('2016-03-14')
    });
    let record3 = this.store.createRecord('sighting', {
      location: 'Asilomar',
      sightedAt: new Date('2016-03-21')
    });
    return [record1, record2, record3];
  }
});

使用 Chrome 浏览器的 Ember Inspector 可以查看该路由的数据,验证只有一个 sighting 实例的 isNew 属性为 true

11.3 黄金挑战

witness 模型添加 title 属性,并设置默认值。在 app/models/witness.js 文件中添加以下代码:

import DS from 'ember-data';
export default DS.Model.extend({
  fName: DS.attr('string'),
  lName: DS.attr('string'),
  email: DS.attr('string'),
  sightings: DS.hasMany('sighting'),
  title: DS.attr('string', { defaultValue: 'Mahatma' }),
  fullName:  Ember.computed('fName', 'lName', function(){
    return this.get('fName') + ' ' + this.get('lName');
  }),
  titleName: Ember.computed('title', 'fullName', function() {
    return this.get('title') + ' ' + this.get('fullName');
  })
});

在创建记录时,除一个记录外,为其他记录设置不同的标题:

import Ember from 'ember';
export default Ember.Route.extend({
  model() {
    let witness1 = this.store.createRecord('witness', {
      fName: "Todd",
      lName: "Gandee",
      email: "fake@bignerdranch.com",
      title: "Mr."
    });
    let witness2 = this.store.createRecord('witness', {
      fName: "John",
      lName: "Doe",
      email: "john.doe@example.com"
    });
    return [witness1, witness2];
  }
});

编辑 app/templates/witnesses.hbs 文件以显示 titleName

{{outlet}}
<h1>Witnesses</h1>
<div class="row">
  {{#each model as |witness|}}
    <div class="col-xs-12 col-sm-6 col-md-4">
      <div class="well">
        <div class="thumbnail">
          <div class="caption">
            <h3>{{witness.titleName}}</h3>
            <div class="panel panel-danger">
              <div class="panel-heading">Sightings</div>
            </div>
          </div>
        </div>
      </div>
    </div>
  {{/each}}
</div>
12. 总结

通过本文的介绍,我们全面了解了 Ember Data 在应用程序数据层管理中的使用方法。从模型的定义开始,我们学习了如何使用 ember g model 命令创建模型文件,并为模型添加属性和关系。接着,我们掌握了如何创建记录、使用 get set 方法操作记录的属性,以及如何使用计算属性处理数据的格式化和展示。在数据检索方面,我们详细了解了 findAll findRecord peekAll peekRecord query queryRecord 等方法的使用场景和特点。最后,我们学习了数据的保存和销毁操作,以及完成了几个挑战任务,进一步巩固了所学知识。

希望本文能够帮助你更好地理解和应用 Ember Data,在实际项目中能够更加高效地管理数据层。如果你在实践过程中遇到任何问题,欢迎随时查阅相关文档或在社区中寻求帮助。祝你在 Ember Data 的学习和应用中取得成功!

下面是一个简单的 mermaid 流程图,展示了使用 Ember Data 管理数据的基本流程:

graph LR
    A[定义模型] --> B[创建记录]
    B --> C[操作记录属性(get/set)]
    C --> D[使用计算属性处理数据]
    D --> E[数据检索]
    E --> F[数据保存/销毁]

这个流程图清晰地展示了使用 Ember Data 管理数据的主要步骤,从模型的定义开始,经过记录的创建、属性操作、数据处理,到数据的检索和保存/销毁,形成了一个完整的数据管理流程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值