Ember Data概述 #

一、Ember Data简介 #

Ember Data是Ember.js的官方数据持久化库,提供了完整的数据管理解决方案。

1.1 核心功能 #

  • 数据模型定义
  • 数据关系管理
  • 数据持久化
  • 缓存管理
  • 与后端API交互

1.2 架构概览 #

text
┌─────────────────────────────────────────────────────────┐
│                    Ember Data                            │
├─────────────────────────────────────────────────────────┤
│                                                          │
│   Store ←→ Adapter ←→ Serializer ←→ Backend API         │
│     │                                                   │
│     ▼                                                   │
│   Model (Record)                                        │
│     │                                                   │
│     ▼                                                   │
│   应用组件/模板                                          │
│                                                          │
└─────────────────────────────────────────────────────────┘

1.3 核心概念 #

概念 说明
Store 数据存储中心
Model 数据模型定义
Adapter 处理API请求
Serializer 数据格式转换
Record 模型实例

二、安装配置 #

2.1 安装 #

Ember Data默认包含在Ember CLI创建的项目中。

bash
# 查看已安装版本
ember show ember-data

2.2 配置 #

javascript
// app/adapters/application.js
import RESTAdapter from '@ember-data/adapter/rest';

export default class ApplicationAdapter extends RESTAdapter {
  namespace = 'api/v1';
}
javascript
// app/serializers/application.js
import RESTSerializer from '@ember-data/serializer/rest';

export default class ApplicationSerializer extends RESTSerializer {
}

三、Store #

3.1 Store概述 #

Store是Ember Data的核心,负责管理所有数据记录。

javascript
import Route from '@ember/routing/route';
import { inject as service } from '@ember/service';

export default class PostsRoute extends Route {
  @service store;

  model() {
    return this.store.findAll('post');
  }
}

3.2 Store方法 #

javascript
// 查询所有
this.store.findAll('post');

// 查询单个
this.store.findRecord('post', 1);

// 条件查询
this.store.query('post', { category: 'tech' });

// 查询单个(条件)
this.store.queryRecord('post', { slug: 'hello-world' });

// 创建记录
const post = this.store.createRecord('post', {
  title: 'New Post',
  body: 'Content...',
});

// 获取所有已加载记录
this.store.peekAll('post');

// 获取单个已加载记录
this.store.peekRecord('post', 1);

四、模型定义 #

4.1 创建模型 #

bash
ember generate model post

4.2 定义属性 #

javascript
// app/models/post.js
import Model, { attr, belongsTo, hasMany } from '@ember-data/model';

export default class PostModel extends Model {
  @attr('string') title;
  @attr('string') body;
  @attr('string', { defaultValue: '' }) excerpt;
  @attr('date') createdAt;
  @attr('date') updatedAt;
  @attr('boolean', { defaultValue: false }) isPublished;
  @attr('number') viewCount;
}

4.3 属性类型 #

类型 说明
string 字符串
number 数字
boolean 布尔值
date 日期
array 数组
object 对象

4.4 默认值 #

javascript
@attr('string', { defaultValue: '' }) title;
@attr('number', { defaultValue: 0 }) count;
@attr('boolean', { defaultValue: false }) active;
@attr('array', { defaultValue: () => [] }) tags;

五、数据操作 #

5.1 创建记录 #

javascript
import Controller from '@ember/controller';
import { inject as service } from '@ember/service';
import { action } from '@ember/object';

export default class PostsNewController extends Controller {
  @service store;

  @action
  async createPost() {
    const post = this.store.createRecord('post', {
      title: 'My First Post',
      body: 'This is the content...',
    });

    await post.save();
  }
}

5.2 读取记录 #

javascript
// 获取所有记录
const posts = await this.store.findAll('post');

// 获取单个记录
const post = await this.store.findRecord('post', 1);

// 条件查询
const posts = await this.store.query('post', {
  category: 'tech',
  page: 1,
});

5.3 更新记录 #

javascript
@action
async updatePost(post) {
  post.title = 'Updated Title';
  await post.save();
}

5.4 删除记录 #

javascript
@action
async deletePost(post) {
  await post.destroyRecord();
}

六、记录状态 #

6.1 状态检查 #

javascript
// 是否新建
post.isNew;

// 是否已保存
post.isSaved;

// 是否有未保存更改
post.hasDirtyAttributes;

// 是否正在保存
post.isSaving;

// 是否已删除
post.isDeleted;

// 是否正在删除
post.isDeleting;

// 是否有效
post.isValid;

// 是否有错误
post.hasErrors;

6.2 回滚更改 #

javascript
post.rollbackAttributes();

6.3 错误处理 #

javascript
@action
async savePost(post) {
  try {
    await post.save();
  } catch (error) {
    console.log(post.errors);
    console.log(error);
  }
}

七、异步关系 #

7.1 异步加载 #

javascript
// 模型定义
export default class PostModel extends Model {
  @belongsTo('user', { async: true }) author;
  @hasMany('comment', { async: true }) comments;
}
handlebars
{{! 模板中使用}}
<p>作者:{{await @post.author.name}}</p>

{{#each (await @post.comments) as |comment|}}
  <p>{{comment.body}}</p>
{{/each}}

7.2 预加载关系 #

javascript
// 在路由中预加载
model() {
  return this.store.findRecord('post', 1, {
    include: 'author,comments',
  });
}

八、缓存策略 #

8.1 后台重载 #

javascript
model() {
  return this.store.findRecord('post', 1, {
    backgroundReload: true,
  });
}

8.2 强制重载 #

javascript
model() {
  return this.store.findRecord('post', 1, {
    reload: true,
  });
}

8.3 缓存清空 #

javascript
// 清空所有缓存
this.store.unloadAll();

// 清空特定类型
this.store.unloadAll('post');

// 清空单个记录
post.unloadRecord();

九、最佳实践 #

9.1 在路由中加载数据 #

javascript
// 好的做法
export default class PostsRoute extends Route {
  model() {
    return this.store.findAll('post');
  }
}

// 避免 - 在组件中加载数据

9.2 使用Ember Data约定 #

javascript
// 后端返回格式
{
  "posts": [
    { "id": 1, "title": "Post 1" },
    { "id": 2, "title": "Post 2" }
  ]
}

9.3 处理错误 #

javascript
@action
error(error, transition) {
  if (error.errors?.[0]?.status === '404') {
    this.router.transitionTo('not-found');
  }
}

十、总结 #

Ember Data核心概念:

概念 说明
Store 数据存储中心
Model 数据模型
Adapter API适配器
Serializer 数据序列化
Record 模型实例

Ember Data提供了完整的数据管理解决方案,是Ember应用的核心组件。

最后更新:2026-03-28