7 javascript relationship ember.js ember-data ember-controllers
这些是我的文件:
楷模
应用程序/模型/ basket.js:
export default DS.Model.extend({
name: DS.attr('string'),
house: DS.belongsTo('house', { async: true }),
boxes: DS.hasMany('box', { async: true })
});
Run Code Online (Sandbox Code Playgroud)
应用程序/模型/ box.js:
export default DS.Model.extend({
qty: DS.attr('number'),
basket: DS.belongsTo('basket'),
cartLines: DS.hasMany('cart-line', { async: true })
});
Run Code Online (Sandbox Code Playgroud)
应用程序/模型/车,line.js:
export default DS.Model.extend({
qty: DS.attr('number'),
box: DS.belongsTo('box'),
product: DS.belongsTo('product')
});
Run Code Online (Sandbox Code Playgroud)
应用程序/模型/ product.js:
export default DS.Model.extend({
name: DS.attr('string'),
price: DS.attr('number')
});
Run Code Online (Sandbox Code Playgroud)
路线
应用程序/路由/ basket.js:
export default Ember.Route.extend({
model(params) {
return Ember.RSVP.hash({
basket: this.store.findRecord('basket', params.basket_id),
boxes: this.store.findAll('box'),
products: this.store.findAll('product')
});
},
setupController(controller, models) {
controller.setProperties(models);
}
});
Run Code Online (Sandbox Code Playgroud)
控制器
应用程序/控制器/ basket.js:
export default Ember.Controller.extend({
subTotal: Ember.computed('boxes.@each.cartLines', function () {
return this.products.reduce((price, product) => {
var total = price + product.get('price');
return total;
}, 0);
})
});
Run Code Online (Sandbox Code Playgroud)
问题:
我是新手,所以我正在学习和制造错误.抱歉.
1)当我第一次进入路线时,哪种是最好的Ember方式来过滤关系?例如,现在我加载我的应用程序中的每个框boxes: this.store.findAll('box').我需要一种方法来不加载我的webapp中的所有框,只是在篮子中的那个.我需要直接从后端"使用过滤器查询"?
更新的问题
2)计算subTotal的最佳Ember方法是什么?现在,通过下面的代码,Ember给了我subTotal,但只是在console.log(tot)承诺之内和之后!为什么这个?我怎么能等待承诺呢?我不明白该怎么做:
subTotal: Ember.computed('basket.boxes.@each.cartLines', function () {
let count = 0;
console.log('subTotal called: ', count);
// It should be 0 ever
count = count + 1;
return this.get('basket.boxes').then(boxes => {
boxes.forEach(box => {
box.get('cartLines').then(cartLines => {
cartLines.reduce(function (tot, value) {
console.log('tot:', tot + value.get('product.price'));
return tot + value.get('product.price');
}, 0);
});
});
});
});
Run Code Online (Sandbox Code Playgroud)
它给了我模板[object Object],因为我也在hbs {{log subTotal}}和控制台中使用它给了我这个:
subTotal called: 0
ember.debug.js:10095 Class {__ember1476746185015: "ember802", __ember_meta__: Meta}
subTotal called: 0
ember.debug.js:10095 Class {__ember1476746185015: "ember934", __ember_meta__: Meta}
ember.debug.js:10095 Class {isFulfilled: true, __ember1476746185015: "ember934", __ember_meta__: Meta}
subTotal called: 0
ember.debug.js:10095 Class {__ember1476746185015: "ember1011", __ember_meta__: Meta}
ember.debug.js:10095 Class {isFulfilled: true, __ember1476746185015: "ember1011", __ember_meta__: Meta}
tot: 3.5
tot: 6
tot: 13.5
tot: 21
tot: 24.5
tot: 27
tot: 3.5
tot: 6
tot: 13.5
tot: 21
tot: 24.5
tot: 27
tot: 3.5
tot: 6
tot: 13.5
tot: 21
tot: 24.5
tot: 27
Run Code Online (Sandbox Code Playgroud)
为什么它显示三次subTotal called: 0,无论是零还是一千或一千种产品.他总是打三次电话subTotal called: 0,为什么?
将计算属性与promises一起使用是否合适?
3)我对这种关系封装是否正确?
更新的问题2:
现在我正在使用此代码,但没有成功:
import Ember from 'ember';
import DS from 'ember-data';
export default Ember.Controller.extend({
totalCount: Ember.computed('basket.boxes.@each.cartLines', function () {
let total = 0;
const promise = this.get('basket.boxes').then(boxes => {
boxes.map(box => {
// const trypromise = boxes.map(box => {
console.log('box:', box);
box.get('cartLines').then(cartLines => {
console.log('cartLines:', cartLines);
const cartLinesPromise = cartLines.map(cartLine => {
console.log('cartLine:', cartLine);
// return cartLine.get('qty');
// return cartLine;
// });
return {
qty: cartLine.get('qty'),
price: cartLine.get('product.price')
};
// return cartLines.map(cartLine => {
// console.log('cartLine:', cartLine);
// return cartLine.get('qty');
// // return {
// // qty: cartLine.get('qty'),
// // price: cartLine.get('product.price')
// // };
// });
})
// });
return Ember.RSVP
.all(cartLinesPromise)
.then(cartLinesPromise => {
console.log('cartLinesPromise:', cartLinesPromise);
// cartLinesPromise.reduce((tot, price) => {
// console.log('tot:', tot);
// console.log('price:', price);
// console.log('tot+price:', tot + price);
// return tot + price, 0;
// });
return total = 10;
// return total;
})
});
});
// return total;
});
return DS.PromiseObject.create({ promise });
})
})
Run Code Online (Sandbox Code Playgroud)
评论是很多尝试.
在模板中我使用:
{{log 'HBS totalCount:' totalCount}}
{{log 'HBS totalCount.content:' totalCount.content}}
Total: {{totalCount.content}}
Run Code Online (Sandbox Code Playgroud)
但promise要有null内容.
哪里我错了?
有return什么不对吗
这段代码"有前途"是否正确?
刚接触技术并没有什么坏处,尤其是当你的问题格式良好且经过深思熟虑时。
这是一个复杂的问题,有很多可能的结局。
最简单的事情就是询问该模型。
鉴于您的模型,您可以执行以下操作:
model(params) {
// we will return basket but make boxes ready
return this.get('store').find('basket', params.basket_id).then(basket => {
return basket.get('boxes').then(() => basket);
});
}
Run Code Online (Sandbox Code Playgroud)
但这有一些限制和优点
编辑:
you need to send ids with basket这意味着basket在您的有效负载中必须提供其盒子的标识。如果是休息 API:{basket: {id: 1, boxes: [1,2,3], ...}. 然后它会检查哪些 id 尚未加载到商店中,并在此处询问 api(假设 id 2 的框已加载):/boxes?ids[]=1&ids[]=3。
model(params) {
const store = this.get('store');
const basket = params.basket_id;
return RSVP.hash({
model: store.find('basket', basket),
boxes: store.query('box', {basket}),
});
},
Run Code Online (Sandbox Code Playgroud)
query参数来进行服务器端过滤编辑:您实际上可以使用
hasManyif you don't like it you would have to use peekAll and filter to check if you have all of them进行检查。
您可以创建 api,以便将框附加到有效负载中,而不是向服务器发送两个请求。
您可以仅加载最少的内容(例如仅加载购物篮),让 ember 继续并渲染页面。它会看到您正在访问
basket.boxes属性并获取它们。这本身看起来不太好,并且需要一些额外的工作,例如旋转器等。但这是加快启动和初始渲染时间的一种方法。
您想要计算深入到异步关系的三个级别的总和,这并不容易。首先,我建议将 TotalPrice 计算属性放入购物篮模型本身。计算属性是延迟评估的,因此不会出现性能下降,这是模型应该能够提供的。
这是一个小片段:
// basket.js
const {RSVP, computed} = Ember;
price: computed('boxes.@each.price', function() {
const promise = this.get('boxes').then(boxes => {
// Assuming box.get('price') is computed property like this
// and returns promise because box must wait for cart lines to resolve.
const prices = boxes.map(box => box.get('price'));
return RSVP
.all(prices)
.then(prices => prices.reduce((carry, price) => carry + price, 0));
});
return PromiseObject.create({promise});
}),
Run Code Online (Sandbox Code Playgroud)
您需要为每个级别编写类似的内容或放弃一些异步关系。您的计算属性的问题在于,它boxes.@each.cartLines不会监听所有可能改变总体价格的内容(例如产品本身价格的变化)。因此它不会反映和更新所有可能的更改。
我会明智地放弃一些异步关系。例如,请求/baskets/2可以侧载其所有盒子、cartLines 甚至产品。如果你的 api 不支持侧面加载,你可以通过加载路由中的所有内容来伪造它(你必须使用第二个示例 - 在盒子进入商店之前,你不能访问盒子)async: false。这将导致计算总价格的计算属性变得更加简单,并且在侧载的情况下还可以减轻服务器和客户端的压力。
// basket.js
const {computed} = Ember;
boxes: DS.hasMany('box', {async: false}),
price: computed('boxes.@each.price', function() {
return this.get('boxes').reduce(box => box.get('price'));
}),
Run Code Online (Sandbox Code Playgroud)
我认为在一个函数中完成所有求和是不可行的、可行的或明智的。你最终会陷入回调地狱或其他类型的地狱。而且这不会成为性能瓶颈。
我制作了jsfiddle,它基本上是上面代码片段的更充实的版本。请注意,它会正确等待并传播价格,这是两个深度承诺,并且在发生变化时也应该更新(我也没有测试这一点)。
| 归档时间: |
|
| 查看次数: |
1299 次 |
| 最近记录: |