2014-09-24 44 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));