Ember - 页面重新加载时丢失的对象相关项目

Ember - object related item lost on page reload

我在 Ember 中有 Order 和 PaymentMethod 模型,具有如下多对一关系:

order.js

export default DS.Model.extend({
    paymentStatus: DS.attr('number', { defaultValue: 1 }),
    paymentMethod: DS.belongsTo('payment-method'),
})

付款-method.js

export default DS.Model.extend({
    name: DS.attr('string'),
    orderPaymentMethods: DS.hasMany('order')
})

订单已保存到数据库中 - 一切正常。然后我有一个路线审查订单,它获得订单模型(我的 API 只返回当前登录用户的订单模型)

评论-order.js

export default Route.extend({
    model() {
        const order = this.store.findAll('order', { include: 'payment_method' }).then((orders) => {
           return orders.filterBy('paymentStatus', 1).get('lastObject');
       });
       return order;
   }
});

在我的评论订单模板中,我打印出付款方式关系,就像这样

{{model.paymentMethod.name}}

这很好用我在创建订单后转换到评论订单路线 - 它打印付款方式的名称。但是,如果我刷新评论订单页面,它会丢失,我不知道为什么!

感谢您提出完整而详细的问题!我将尝试回答,但我没有 100% 的信息,我需要确保这将根据您的具体情况回答问题,但希望它仍然有用,您可以从中提取您需要的信息.

您提到的整体问题,即刷新时数据未正确加载,可能是由于 API 响应没有所需的所有信息。如果您检查 chrome 上的 Web 开发工具,您将能够验证情况是否如此。

如果您打开开发工具,打开网络选项卡并找到正在加载您的数据的查询,那么我们可以验证这一点。我不知道您对开发工具有多熟悉,但如果您打开它们并刷新页面,您将看到浏览器发出的所有请求。然后您可以按 XHR 过滤以找到 API 查询:

然后您将能够单击相关请求并使用 预览 选项卡浏览可用数据:

通过查看此数据,您将能够验证是否建立了所需的关系,并且您还能够确认 includes 部分中是否也包含正确的数据 JSON:API回应。有关这应该是什么样子的示例,您可以查看 examples page for the official JSON:API documentation

我们花了一些时间尝试使用 Mirage 来复制您的问题,以便我们可以显示您遇到的确切问题。这是一个玩具示例,但它确实复制了错误并显示了我上面描述的方法如何解决问题。

首先,我完全按照您的描述复制了您的模型,然后我创建了一个 Mirage 端点来处理获取单个订单的请求:

  this.get('/orders/:id', (schema, request) => {
    let responseData = {
      data: {
        id: request.params.id,
        type: 'orders',
        attributes: { 'payment-status': 1 },
        relationships: {
          "payment-method": {
            data: { id: "42", type: "payment-methods" }
          }
        }
      }
    };

    if(request.queryParams.include === "payment_method") {
      responseData.included = [{
        type: "payment-methods",
        id: "42",
        attributes: { name: "Credit Card" }
      }];
    }

    return responseData;
  });

您会看到,如果 queryParams 包含 ?include=payment_method,它会确保付款方式包含在响应中 JSON。


关于您的示例,我注意到的另一件事是您在 review-order.js 路由中的 model() 挂钩似乎有点不合常规。 review-order 路线,并确保我在过渡到它时传递了订单对象。这是我的路由器定义:

Router.map(function() {
  this.route('review-order', { path: '/review/:id'});
});

然后我创建了一个带有 createOrder() 操作的简单按钮来模拟创建订单:

  actions: {
    createOrder() {
      let paymentMethod = this.store.createRecord('payment-method', {
        name: 'Credit Card'
      });

      let order = this.store.createRecord('order', {
        id: 'not-null',
        paymentStatus: 1,
        paymentMethod: paymentMethod,
      });

      // we don't actually save because I don't have a backend setup correctly
      // order.save().then(() => { })

      // when we're done transition to review route with the model
      this.transitionToRoute('review-order', order);
    }
  }

如您所见,我在 transitionToRoute() 调用中包含了订单对象。

然后我们可以稍微简化您路线中的 model() 钩子:

  model(params) {
    return this.store.findRecord('order', params.id, { include: 'payment_method'})
  }

希望能帮助您解决问题


这个问题作为 "May I Ask a Question" 第 2 季第 4 集的一部分得到了回答。如果您想看到我们完整讨论这个答案,您可以在此处观看视频:https://www.youtube.com/watch?v=W1udsGt8F9g