如何使用 REST API 使用 Ember 数据?

How to work with REST API using Ember data?

我正在尝试将 ember 数据与来自服务器的 REST API 一起使用。该项目非常简单,与 Fetch API 配合使用效果很好,但我想使用 Ember data 实现相同的结果并理解它的原理。我无法使用此配置的 ember twiddle。下面将是项目的主要部分。它由 Ember CLI 版本 4.0.1.

制作

来自 url http://localhost:3000/api/v1/itemsJSON 回复看起来像:

[
  {
    "id": 1,
    "name": "Item 1",
    "description": "12345",
    "created_at": "2022-01-07T11:43:21.755Z",
    "updated_at": "2022-01-07T11:43:21.755Z"
  },
  {
    "id": 2,
    "name": "Item 2",
    "description": "22222",
    "created_at": "2022-01-07T11:43:29.787Z",
    "updated_at": "2022-01-07T11:43:29.787Z"
  },
  {
    "id": 3,
    "name": "Item 3",
    "description": "33333",
    "created_at": "2022-01-07T11:43:37.885Z",
    "updated_at": "2022-01-07T11:43:37.885Z"
  }
]

来自单个项目请求的响应,例如 http://localhost:3000/api/v1/items/1:

{
    "id": 1,
    "name": "Item 1",
    "description": "12345",
    "created_at": "2022-01-07T11:43:21.755Z",
    "updated_at": "2022-01-07T11:43:21.755Z"
}

app/models/item.js:

import Model, { attr } from '@ember-data/model';

export default class ItemModel extends Model {
  @attr name;
  @attr description;
}

app/routes/items.js:

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

export default class ItemsRoute extends Route {
  @service store;
  async model() {
    return this.store.findAll('item');
  }
}

app/routes/item.js:

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

export default class ItemRoute extends Route {
  @service store;
  async model(params) {
    return this.store.findRecord('item', params.id);
  }
}

app/templates/items.hbs:

{{#each @model as |item|}}
  <LinkTo @route='item' @model={{item}}>{{item.name}}</LinkTo>
{{/each}}

app/adapters/application.js:

import RESTAdapter from '@ember-data/adapter/rest';

export default class ItemAdapter extends RESTAdapter {
  host = 'http://localhost:3000';
  namespace = 'api/v1';

  buildURL(...args) {
    return `${super.buildURL(...args)}.json`;
  }
}

app/serializers/application.js:

import RESTSerializer from '@ember-data/serializer/rest';

export default class ItemSerializer extends RESTSerializer {}

app/router.js:

import EmberRouter from '@ember/routing/router';
import config from 'dist/config/environment';

export default class Router extends EmberRouter {
  location = config.locationType;
  rootURL = config.rootURL;
}

Router.map(function () {
  this.route('items');
  this.route('item', { path: '/:id' });
});

当我在 ember 客户端上移动到路由 /items 时,控制台中出现以下错误:

WARNING: Encountered "0" in payload, but no model was found for model name "0" (resolved model name using <dist@serializer:item::constructor>.modelNameFromPayloadKey("0"))

“1”和“2”同样的错误。该模板不会在 each 循环中呈现链接。

可能Ember dataREST API有一些特点,我很想弄明白。感谢关注!

我认为您遇到此问题是因为您的数据不是 RESTSerializer 格式,而是 JSONSerializer one:

the JSONSerializer expects the response to be a JSON object that looks similar to this

{
  "id": "1",
  "title": "Rails is omakase",
  "tag": "rails",
  "comments": ["1", "2"]
}

所以我想你应该只用这个。

如果出于任何原因您想保留 RESTSerializer 您应该 return 您的数据类似于此格式:

{
"item":
  {
    "id": 1,
    "name": "Item 1",
    "description": "12345",
    "created_at": "2022-01-07T11:43:21.755Z",
    "updated_at": "2022-01-07T11:43:21.755Z"
  }
}

或列表

{
"items": [
  {
    "id": 1,
    "name": "Item 1",
    "description": "12345",
    "created_at": "2022-01-07T11:43:21.755Z",
    "updated_at": "2022-01-07T11:43:21.755Z"
  },
  ...
]