2013-08-18 32 views
2

我有一個視圖,顯示給定位置的所有員工的小編輯表單,一個在另一個下方。爲每位員工顯示的一個控件是150個城市的精選列表。該選擇列表上的更改事件會將員工轉移到其他位置。如何在Knockout.js中重用選擇列表以獲得更好的性能?

<select data-bind="options: $root.locations(), 
    optionsCaption: 'Please choose...', 
    optionsText: function(item) { return item.locationname(); }, 
    optionsValue: 'uuid', 
    value: reassign_to_locationuuid, 
    event: {change: $root.reassignLocation}"> 
</select> 

這工作得很好,但最大的位置有79人,而當網頁加載,它需要一段時間 - 沒有什麼瘋狂的,大約只有10秒,我在地方,而一個好的催眠加載動畫用戶等待。但我不知道如何提高加載速度和我的Knockout-fu,在這成爲一個更大的問題之前。

當我加載這些選擇列表註釋掉的頁面時,它呈現在< 2s中。這個放緩是因爲[我的糟糕的設計]讓KO重複了79次選擇150個項目的清單。由於他們是完全相同的列表,每個人都綁定到不同的員工的reassign_to_locationuuid屬性,我不知道它是否可以運行得更快。

這是一個艱難的一個谷歌,因爲:

  • 在knockout.js與多選列表中進行搜索帶來了一噸的選擇列表,使信息的多重選擇
  • 搜索重新使用模板在knockout.js帶來了很多有用的信息在命名模板

我試着去與命名模板,但學會了在那些似乎是你想要傳遞不同數據到相同佈局的情況下 - 我每次都傳遞相同的數據。

當我搜索knockout.js性能我發現瑞恩·尼邁耶的http://www.knockmeout.net/2012/06/knockoutjs-performance-gotcha-3-all-bindings.html

要嘗試以確定是否有描述問題(所有綁定一次發射)是我的問題太多,我下載了麥可思的knockout-從https://github.com/mbest/knockout-repeat重複和改變了我的選擇列表使用這種方法:

<select data-bind="value: reassign_to_locationuuid, 
        event: {change: $root.reassignLocation}"> 
    <option value="">Please choose...</option> 
    <option data-bind="repeat: $root.locations()" 
      data-repeat-bind="attr: { value: $item().uuid() }, 
           text: $item().locationname()"> 
    </option> 
</select> 

......但時機是近乎相同,所以似乎沒有吧。

謝謝邁克爾&瑞恩回答Knockout with repeat binding: Initially selected value being overwritten - 我昨天發現瞭解決方案,它幫助我得到了上面的敲除重複測試的工作(它不會更快)。

鑑於reassign_to_locationuuid財產爲每一位員工開始爲空時,頁面加載,而這些名單中的任何一個的第一個變化會從該頁面進行瀏覽,當reassignLocation事件觸發,我覺得像我做錯了什麼。

  1. 在這種情況下,我可以讓KO做大部分工作而不是79次嗎?
  2. 我是不是應該在這個部位使用KO?也許我不需要這些列表中的所有豐富的KO約束優點?
  3. 這個列表構建可能會以某種方式異步發生嗎?

回答

1

是的,可以爲每個人重複使用相同的位置列表。我通過剝離一些屬性簡化了您的任務,並編寫了問題的示例實現。

http://jsfiddle.net/PqqHK/

300的位置和100人被裝載一次(有載)。每個人的位置列表不需要分別爲每個人渲染,因爲人員數據保持並跟蹤位置ID,並且在人員變更時選擇了select中的適當位置項目。

<div data-bind="with: selectedPerson"> 
    <p> 
     <b>Id:</b> 
     <span data-bind="text: id"></span> 
    </p> 
    <p> 
     <b>Name:</b> 
     <span data-bind="text: name"></span> 
    </p> 
    <p> 
     <b>Location:</b> 
     <select data-bind="options: $root.locations, 
      optionsValue: 'id', 
      optionsText: 'name', 
      value: location"></select> 
     <i>Select another value to relocate!</i> 
    </p> 
</div> 

人的構造函數:

function Person(id, name, locId) { 
    this.id = id; 
    this.name = name; 
    this.location = ko.observable(locId); 
} 

型號:

ko.applyBindings(vm = { 
    persons: persons, 
    locations: locations, 
    selectedPerson: ko.observable() 
}); 
+1

謝謝!就我而言,每個人都必須展示自己的位置選擇列表。我真的很想學習如何儘可能快地讓這種較重的視圖變得更快,所以我分叉http://jsfiddle.net/8NkqC/2/使用foreach來顯示每個人的一種表單。我還將列表項數量與我最大的真實案例數量加倍......這個小提琴的運行速度仍然比我的代碼快3倍! 我認爲原因是我對我的傳入JSON使用ko.mapping(),所以每個項目的每個屬性都是可觀察的。我會重構它,以便我只觀察我**需要的**,就像你的例子。 – Emrys

+0

好的嘗試。我不知道你想要在人們頁面上單獨顯示人物。在你的案例中還有一個選項可以幫助提高長列表的性能 - 分頁。每頁渲染20或30人將大大提高加載速度,而不是一次呈現數百個。 –

相關問題