【问题标题】:Ordering a list of knockout components订购淘汰组件列表
【发布时间】:2014-09-26 05:24:49
【问题描述】:

我有一个淘汰组件列表

  <!-- 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。

我希望数组中的项目保留为组件,以便使它们易于重复使用。

有没有办法访问创建的视图模型,以便我可以根据它的属性进行排序?

【问题讨论】:

  • 我想您可以使用 requireJS(或您使用的任何模块加载器)手动获取视图模型并检查属性。但在我看来,这闻起来像是糟糕的设计。排序顺序应该取决于数据,而不是视图模型中的某些硬编码属性。如果 viewmodel 属性不是硬编码的,而是取决于您传递的数据,那么应该可以在排序函数中应用相同的逻辑,直接使用数据。 (通过数据我的意思是你的jsonItem。) TL;DR:你不应该需要视图模型来对你的数组进行排序。请改用原始数据。
  • 没错,这就是我刚刚绕过它的方式,但它本身就很臭。提供排序/排序整数的逻辑应该封装在组件的视图模型中,因为它是与之相关的逻辑。假设我有 10 个不同的组件,它们计算它们的排序索引略有不同,当基于类型时,我必须有某种单独的排序提供程序。我认为每个视图模型都封装一个函数会更好。
  • 我不同意这个逻辑应该在视图模型本身内部。排序将与其他项目(组件)相关,因此属于“了解”所有组件的单独模块。但这只是从概念上讲,它是一条细线,有点取决于您的语义。您能否详细说明如何确定组件的“排序整数”?你的最终结果应该是什么?只是按组件类型排序,还是基于数据,或两者兼而有之?仍然很难看出视图模型上的方法增加了什么价值。
  • 其实是历史事件的时间线。对于大多数项目,它类似于日期,但是我们有多个 call to action 项目,它们不是时间线事件,但我们希望它们位于特定位置。也许你是对的,应该有一个单独的排序模块。它可能会使其更具可测试性。

标签: knockout.js knockout-components


【解决方案1】:

在下一个版本的 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));

【讨论】:

    猜你喜欢
    • 2013-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-20
    • 2016-02-29
    • 1970-01-01
    • 1970-01-01
    • 2012-11-10
    相关资源
    最近更新 更多