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 bazesbazes: computed('bazesArrays.[]') -- 扁平化bazesArraysbazesNames: computed('bazes.@each.name') -- 通过name映射bazes

如何让链条变短

请注意,您可以依靠 bar.bazes 是一个永远不会被其他数组替换的关系数组(仅其内容发生变化,但数组对象保持不变)这一事实,使该链更短(但不一定性能更高)一样)。

bazesArrays: computed('foos.@each.bars')-- 将foos 映射到bars,展平,然后映射到bazes。您将拥有一系列 baze。 bazes: computed('bazesArrays.[]') -- 扁平化bazesArraysbazesNames: 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 深一层,但我有两层深的关系[重复]的主要内容,如果未能解决你的问题,请参考以下文章

js中关于给两层的li标签添加class的问题,求大神解答!

递归函数输出一个狂野的多维数组,希望它深一层

Ember.js:让组件观察商店物品的值变化

Ember:在#each 循环中使用索引选择对象形式数组

Ember.js 多个,命名的插座用法

each 中的 link-to 未删除 ember 中的旧模板