2014-09-05 47 views
2

我有一個自定義綁定,與Scribe接口,這是一個可以滿足需求的所見即所得的編輯器。它更新相關的可觀察到的,當編輯內容的變化,並更新編輯器時,相關的可觀察到的作用:敲除:避免綁定中的循環更新

ko.bindingHandlers.editor = { 
    init: function(element, valueAccessor) { 
    var $element = $(element), 
     content  = ko.unwrap(valueAccessor()), 
     scribe; 

    // create a new editor instance 
    scribe = new Scribe(element); 

    // store it for later access in our 'update' handler 
    $element.data('scribe', scribe); 

    // set the initial editor content 
    scribe.setContent(content); 

    // update the observable whenever the editor changes 
    scribe.on('content-changed', function() { 
     var observable = valueAccessor(), 
      content  = scribe.getHTML(); 

     observable(content); 
    }); 
    }, 
    update: function(element, valueAccessor) { 
    var $element = $(element), 
     content  = ko.unwrap(valueAccessor()); 

    // update the editor content when the observable changes 
    $element.data('scribe').setContent(content); 
    } 
}; 

問題是這樣的:

  1. 用戶類型分爲編輯
  2. 編輯器組件發送「更改」事件
  3. 事件處理程序更新可觀察的
  4. 綁定的「更新」處理程序被觸發,將更改寫回到edi tor

通常情況下,這不會是一個大問題,只是沒有必要。但在我的情況下,editor.setContent具有將光標位置重置爲輸入開頭的副作用 - everything you enter is reversed

我需要更新編輯器,如果 - 並且只有 - 如果 - observable在應用程序中的其他位置被更改。我在尋找的是一種避免更新編輯器的方法,它首先在編輯器本身中進行更改。

我該如何最好地避免這些循環更新?

更新: 我已經找到避開我的眼前問題的一個明顯的方式 - 在更新處理,簡單地比較可觀察到的內容到當前編輯的內容進行更新之前:

if ($element.data('scribe').getHTML() !== content) { 
    $element.data('scribe').setContent(content); 
    } 

我會如果僅僅是爲了避免不必要的更新呼叫,仍然對一般性回答感興趣。

+0

我不完全理解這個問題,但這可能有所幫助:http://knockoutjs.com/documentation/rateLimit-observable.html或可能看起來使用的是valuHasMutated,示例在這裏:http://jsfiddle.net/98e52/118/ – Tanner 2014-09-05 13:27:04

+0

謝謝@Tanner!我已經重寫了這個問題 - 希望現在這個問題變得更加清晰。 – janfoeh 2014-09-05 14:22:57

+2

除了檢查是否真的有變化之外,還有一種想法是將'update'功能移到'init'中的計算中,並在更新observable之前檢查您設置的共享標誌,然後再清除。計算將如下所示:'ko.computed(function(){// your update stuff},null,{disposeWhenNodeIsRemoved:element});' – 2014-09-05 14:58:22

回答

1

基於RPNiemeyers recommendation,我提出的可觀察到的 - 從綁定update處理機>組件更新功能集成到init處理程序:

ko.bindingHandlers.editor = { 
    init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { 
    var $element    = $(element), 
     content     = ko.unwrap(valueAccessor()), 
     ignoreObservableChanges = false, 
     scribe; 

    scribe = new Scribe(element); 

    $element.data('scribe', scribe); 

    scribe.setContent(content); 

    scribe.on('content-changed', function() { 
     var observable = valueAccessor(), 
      content  = scribe.getHTML(); 

     ignoreObservableChanges = true; 
     observable(content); 
     ignoreObservableChanges = false; 
    }); 

    valueAccessor().subscribe(function(newValue) { 
     if (ignoreObservableChanges) { 
     return; 
     } 

     scribe.setContent(newValue); 
    }); 
    } 
}; 

兩個組件 - >觀察到的更新程序和可觀察到的 - >組件更新現在在他們的範圍內共享ignoreObservableChanges標誌,因此前者可以指示後者何時跳過更新。