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
我在 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