Ember js @each 深一层,但我有两层深的关系[重复]
Posted
技术标签:
【中文标题】Ember js @each 深一层,但我有两层深的关系[重复]【英文标题】:Ember js @each one level deep but I have a two deep level relationship [duplicate] 【发布时间】:2016-06-30 21:25:46 【问题描述】:我必须访问控制器上两层深度的属性,但 []
只能通过 emberjs 指南访问一层深度。
model(params)
params.paramMapping =
page: "page",
perPage: "per_page",
total_pages: "pages"
;
return this.findPaged('contractf', params);
,
setupController(controller, model)
model.forEach(function(item)
item.set('sale_price', item.get('dealers_sched_id.sale_price'));
);
controller.set('content', model);
,
上面,我的模型基本上是在 contractf 模型中以分页格式获取所有记录。然后我设置我的控制器并循环遍历所有这些模型并绑定一个 sale_price
属性,该属性进入它的关系,以在正确的模型关系中获取 sale_price。
现在在我的模板中,我有这个:
new_suggested_price: Ember.computed('selectedItems', 'selectedItems.[].sale_price', function()
var ret = 0;
this.get('selectedItems').filterBy('car_used', 'N').forEach(function(contract)
var salePrice = contract.get('sale_price');
if (salePrice)
ret += (salePrice*100);
);
return ret/100; // We *100/100, so we avoid a floating point calc error.
),
基本上只是给我一个易于格式化的数字。如您所见,它取决于 selectedItems (基本上是模型,但按属性过滤)。所以我必须进入每个模型项并找到我设置的sale_price
I 属性,如果它发生变化,这个计算属性将更新。阅读 Ember 的指南,我无法做到 selectedItems.[].dealers_sched_id.sale_price
,因为它只深入了一层。
我认为在 setupController 上设置一个属性可以解决这个问题,但似乎并没有因为我仍然将 NaN
作为 sale_price
值。
现在,如果我将 setTimeout 函数设置为 500 毫秒,它会很好地填充。如何在页面加载时定义它?
感谢您的帮助。
【问题讨论】:
@locks 说得很好。我什至没有注意到无效的依赖键 @locks 谢谢!这对我有用:'selectedItems.@each.isProcessing', 'selectedItems.@each.dealers_sched_id,sale_price'
【参考方案1】:
为什么会出现这个问题
Ember API 确实允许您在计算的属性依赖项中仅使用一级 @each
/[]
。
此限制可能是人为的,因为使用两个或更多 @each
级别会对内部观察者维护产生巨大的性能影响。
因此,您必须避免在 CP 依赖链中出现多个 @each
/[]
。
如果你不能用 N 根蜡烛做蛋糕,那就做 N 个蛋糕,每个蛋糕用一根蜡烛
但有时您的业务要求您必须达到或更高级别。
不要害怕!这可以通过一系列计算属性来实现,其中每个属性只有一个@each
级别。
说,你有 Foo、Bar 和 Baz 模型并且想要依赖
foos.@each.bars.@each.bazes.@each.name
这是您需要创建的一系列计算属性:
barsArrays: computed('foos.@each.bars')
-- 映射 foos
通过 bars
。您将拥有一组条形数组。
bars: computed('barsArrays.[]')
-- 将其展平以接收一系列条形。
bazesArrays: computed('bars.@each.bazes')
-- 映射bars
by bazes
。
bazes: computed('bazesArrays.[]')
-- 扁平化bazesArrays
。
bazesNames: computed('bazes.@each.name')
-- 通过name
映射bazes
。
如何让链条变短
请注意,您可以依靠 bar.bazes
是一个永远不会被其他数组替换的关系数组(仅其内容发生变化,但数组对象保持不变)这一事实,使该链更短(但不一定性能更高)一样)。
bazesArrays: computed('foos.@each.bars')
-- 将foos
映射到bars
,展平,然后映射到bazes
。您将拥有一系列 baze。
bazes: computed('bazesArrays.[]')
-- 扁平化bazesArrays
。
bazesNames: computed('bazes.@each.name')
-- 映射bazes
by name
。
这是一个工作演示:http://emberjs.jsbin.com/velayu/4/edit?html,js,output
【讨论】:
我有一个多对一的关系。selectedItems.[].dealers_sched_id.sale_price
是我需要运行的。
array.[].property
不是真实的东西,所以它的行为可能不会像您预期的那样。
我猜这是个错误:bars: computed('barz.[]')
,不应该是bars: computed('barsArrays.[]')
吗?
帕沃尔:你是真正的 MVP。
扁平化步骤必须是单独的计算属性是否有特殊原因?例如你不能只有bars: computed('foos.@each.bars')
和names: computed('bars.@each.name')
吗?【参考方案2】:
model.forEach(function(item)
item.set('sale_price', item.get('dealers_sched_id.sale_price'));
);
在这里的这一行中,您实际上是在尝试创建一个别名,这是正确的想法,因为它是一个“模型级别”的关注点......您将在控制器级别执行此操作。
您可以在模型定义上创建computed.alias('dealers_sched_id.sale_price')
,并避免所有额外的计算属性层。
编辑:在您的情况下,我们正在处理异步关系
这意味着您需要注意,当关系承诺仍在自行解决时,您并不总是可以使用该值。您收到NaN
的原因是,belongsTo 在技术上仍在“加载”...因此您尝试执行的任何同步功能都可能对您失败。
当您查看提供给您的两个答案时,涉及计算属性,了解这两种方法将工作......当承诺解决时,它们将计算并重新计算。
在您的代码中的某处,您可能正在尝试访问 eventual 值,在它真正为您准备好之前...可能是 alert()
console.log()
或 Ember 的同步生命之一-循环钩子(提示:setupController)?
另一种方法,可能是使用您的路线的model()
钩子或afterModel()
在解析路线之前请求dealers_sched_id
对象......它可能不太理想,但它会确保您拥有所有数据您需要在尝试使用这些值之前。
【讨论】:
我尝试将别名放在模型上,它不会产生任何结果。如果没有设置计时器,它仍然会出现 NaN。dealers_sched_id
是异步关系吗?还是嵌入对象?
这是异步关系!属于
@HaleyShillig 我更新了我的答案,也许可以提供更多帮助以上是关于Ember js @each 深一层,但我有两层深的关系[重复]的主要内容,如果未能解决你的问题,请参考以下文章