遇到了Ember.js将计算属性交给模板的问题

Got stuck with Ember.js handing over computed property to template

本文关键字:问题 属性 Ember js 计算 遇到      更新时间:2023-09-26

我对成员开发很陌生,需要帮助处理这类任务:

目前,我正在一个ember cli应用程序中使用Fixtures。有关的两种型号是:

var Recipe = DS.Model.extend({
   title: DS.attr('string'),
   body: DS.attr('string'),
   ingredients: DS.hasMany('ingredients',{async: true}),
   recipeCategory: DS.belongsTo('recipeCategory', {async: true})
});
var Ingredient = DS.Model.extend({
   title: DS.attr('string'),
   portion: DS.attr('string'),
   groupTag: DS.attr('string'),
   recipe: DS.belongsTo('recipe')
});

虽然通过嵌套路线列出特定配方的所有成分(也进行了排序)没有问题,但

this.resource('recipes',function(){
   this.resource('recipe', {path: '/:recipe_id'});
});

我在按groupTag对配料进行分组时遇到了大问题。分组的逻辑不是问题所在,但我在访问控制器中的模型以获取计算属性时遇到了竞争条件,或者在尝试处理模板中的promise时遇到了框架错误。

以下是相关模板:

//recipe.hbs
<strong>{{recipeCategory.title}}</strong>
<h3>{{title}}</h3>
{{render 'ingredients' ingredients}}
//ingredients.hbs
<strong>Zutaten</strong>
<ul>
    {{#each groupedIngredients}}
      <li>{{group}}
        <ul>
            {{#each items}}
                <li>{{portion}} {{title}}</li>
            {{/each}}
        </ul>
      </li>
    {{/each}}
</ul>

我的配料控制器看起来像这样:

var IngredientsController = Ember.ArrayController.extend({
   sortProperties: ['title'],
   sortedIngredients: Ember.computed.sort('model', 'sortProperties'),
   groupedIngredients: function(){
       return this.get('model').then(function(ingredients){
          var groupTags = ingredients.mapBy('groupTag').uniq();
          var groupedIngredients = groupTags.map(function(gtag){
            return {
                group: gtag,
                items: ingredients.map(function(item){
                  if ( item.get('groupTag') == gtag){
                    return item;
                  }
                }).compact()
             };
         });
        console.log(groupedIngredients);
        return groupedIngredients;
      });
  }.property('model')
});

promise中的控制台日志很好,但我不能将promise返回给模板进行评估:

Uncaught Error: Assertion Failed: The value that #each loops over must be an Array. You passed {_id: 158, _label: undefined, _state: undefined, _result: undefined, _subscribers: } 

当我删除promise并只处理这个.get('model')时,计算的数组中充满了未定义的值,导致模型似乎没有完全加载。我如何修复这个问题,以这种方式处理异步模型数据?谢谢

您不需要在挂在get('model')上的then中进行计算。当您在代码中达到这一点时,模型已经解决并准备就绪。路由器已经确保模型承诺在继续之前得到解决。

因此:

groupedIngredients: function(){
    var ingredients = this.get('model');
    var groupTags = ingredients.mapBy('groupTag').uniq();
    var groupedIngredients = groupTags.map(function(gtag){
        return {
            group: gtag,
            items: ingredients.map(function(item){
                if ( item.get('groupTag') == gtag){
                    return item;
                }
            }).compact()
        };
   });
   console.log(groupedIngredients);
   return groupedIngredients;
}.property('@each.groupTag')

为了避免必须使用compact,只需切换到使用filter:

items: ingredients.filter(function(item){
    return item.get('groupTag') === gtag;
}

与相同

items: ingredients.filterBy('groupTag', gtag)

这里有一个groupBy作为计算属性的实现,您可以对其进行调整,如果它有效,您只需执行

groupedIngredients: Ember.computed.groupBy('groupTag')

我的代码也有类似的问题,它通常处理为计算属性设置错误的依赖关系。

根据你的代码,我会说你的groupedIngredients:property可能应该是这样的:

.property('@each.groupTag')

一旦设置正确,您应该能够从控制器中删除promise,因为一旦promise实现,它就会自动更新。