2014-09-24 93 views
1

我淘汰赛组件订购淘汰赛的组件列表

<!-- ko foreach: myComponents --> 
    <div data-bind="component: $data"></div> 
    <!-- /ko--> 

列表下面是我如何创建我的组件定义观察到的阵列,这使得预期。

createComponents = function(jsonData) { 
    var components; 
    components = _.map(jsonData, function(jsonItem) { 
     switch (jsonItem.type) { 
     case 0: 
      return { 
      name: "component-type-0", 
      params: jsonItem 
      }; 
     case 1: 
      return { 
      name: "component-type-1", 
      params: jsonItem 
      }; 
     default: 
      throw new Error("No case for type " + jsonItem.type); 
    }); 

    this.myComponents(components); 
    }; 

但是我不知道如何对它们进行排序。我的数组只有namejsonData,但不包含创建组件时创建的viewModel。

我想数组中的项目保留为组件,以便让它们轻松重用。

有没有办法访问创建的viewModel,所以我可以基于它的属性进行排序?

+0

我想你可以使用requireJS(或者你使用的任何模块加载器)手动获取viewmodels并检查属性。但是,这听起来像糟糕的设计。排序顺序应该取决于数据,而不是视图模型中的某些硬编码属性。如果viewmodel属性没有进行硬编码,但取决于您传递的数据,那么应该可以在排序函数中直接使用数据应用相同的逻辑。 (通过数据我的意思是你的'jsonItem'。)TL; DR:你不应该需要viewmodels能够排序你的数组。改用原始数据。 – 2014-09-24 11:17:25

+0

的确,这就是我刚刚解决这个问题的方式,但它本身很臭。提供排序/排序整数的逻辑应该封装在组件的视图模型中,因为它的逻辑与此相关。假设我有10个不同的组件,它们的计算排序索引的方式稍有不同,我不得不在某种类型的单独排序提供程序中使用它。对于每个视图模型来说,我认为封装一个函数会更好。 – Neil 2014-09-24 11:25:45

+0

我不同意这个逻辑应该在viewmodel内部。排序将相对于其他项目(组件),因此属于单独的“知道”所有组件的模块。但是从概念上讲,这是一条细线,它依赖于语义。你能否详细说明一下如何确定组件的“排序整数”?你最终的结果应该是什么?简单地按组件类型排序,还是基于数据或两者的组合?仍然很难看到视图模型上的方法增加了什么价值。 – 2014-09-24 11:33:05

回答

2

通过Knockout的下一个版本,可能有一种方法可以从父级访问组件视图模型,但它目前不是Knockout的一部分。 (请参阅https://github.com/knockout/knockout/issues/1475https://github.com/knockout/knockout/issues/1533

我想出了一种方法来包含使用组件视图模型调用的组件绑定的回调。

这里是它的工作进行排序的一组部件的一个示例:http://jsfiddle.net/mbest/a6f3fmzt/

第一部分是一个自定义绑定,需要一个callback参数并将其注入到用于component结合params值。

ko.bindingHandlers.componentWithCallback = { 
    init: function(element, valueAccessor, ignored1, ignored2, bindingContext) { 
     function newValueAccessor() { 
      var value = ko.unwrap(valueAccessor()); 
      if (value.callback) { 
       value.params = ko.utils.extend(
        { callback: value.callback }, 
        value.params); 
      } 
      return value; 
     } 
     ko.applyBindingAccessorsToNode(
      element, { component: newValueAccessor }, bindingContext); 
    } 
}; 

第二部分是包装组件加载器,在创建视图模型实例后调用回调函数。

ko.components.defaultLoader.loadViewModel = (function (original) { 
    return function (errorCallback, viewModelConfig, callback) { 
     function newCallback(createViewModel) { 
      return callback(function (params, componentInfo) { 
       var componentVM = createViewModel.call(this, params, componentInfo); 
       if (params.callback) { 
        params.callback.call(null, componentVM); 
       } 
       return componentVM; 
      }); 
     } 
     return original.call(this, errorCallback, viewModelConfig, newCallback); 
    } 
}(ko.components.defaultLoader.loadViewModel));