订购淘汰组件列表

时间:2014-09-24 10:54:19

标签: knockout.js knockout-components

我有一个淘汰组件列表

  <!-- 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,以便根据其属性进行排序?

1 个答案:

答案 0 :(得分:2)

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

我已经想出了一种方法,可以使用组件视图模型调用组件绑定的回调。

以下是一个用于对一组组件进行排序的示例:http://jsfiddle.net/mbest/a6f3fmzt/

第一部分是一个自定义绑定,它接受callback参数并将其注入params绑定的component值。

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));