2016-03-07 4 views
0

Я только начал использовать нокаут, но я уже был опытным с MVVM, применяемым в WPF. Проблема, с которой я сталкиваюсь, заключается в том, что моя модель представления нокаута, обертывающая объект модели, не обновляет эту оригинальную модель. Вот небольшой пример:Связывание нокаутом не обновляет модель

HTML

<select name="size" id="sel-size" data-bind="options: sizes, value: size"></select> 

JS

// default settings 
var settings = { 
    size: 5 
}; 

// settings view model 
var settingsVM = function() { 
    return { 
     sizes: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 
     size: ko.observable(settings.size) 
    } 
}(); 

// subscribe to changes 
settingsVM.size.subscribe(function() { 
    alert("Model: " + settings.size + "/VM: " + settingsVM.size()); 
}) 

ko.applyBindings(settingsVM); 

View in JSFiddle

Когда выпадающий выбор изменяется, только settingsVM.size() из модели представления обновляется, но settings.size из модели остается прежней.

Кажется, что инициализация observable со ссылкой не поддерживает эту ссылку в качестве поля поддержки для аксессуара свойства. Что мне не хватает в MVVM-способе нокаута?

ответ

0

Когда вы меняете значение выбора, оно фактически переписывает содержимое вашего наблюдаемого размера. Если вы хотите настроить компоновку типа резервного копирования, вам придется использовать вычисляемое наблюдение с чтением/записью.

Кроме того, если вы хотите обновить исходный объект 'settings', вам нужно будет решить это, а не только свойство settings.size. Что-то, как это будет держать оригинальную модель на этапе с выбора:

// settings view model 
var settingsVM = function() { 
    var self=this; 
    self.settings = ko.observable({ 
    size: 5 
    }); 
    self.sizes = [{size:1},{size:2},{size:3},{size:4},{size:5}]; 
    self.size = ko.computed({ 
      read:function(){ 
      return self.settings(); 
      }, 
      write:function(val){ 
      self.settings(val); 
    }}); 
    self.size.subscribe(function() { 

      alert("Model: " + self.settings().size + "/VM: " + self.size().size); 
     }); 
}; 

ko.applyBindings(new settingsVM()); 

JSFiddle

0

Маленький грязный секрет Нокаут, что это на самом деле не MVVM. Он не имеет структуры для моделирования данных отдельно от viewmodeling, поэтому это просто VVM. В обычном дизайне приложений модель данных находится на сервере, а «модель» в приложении представляет собой набор простых подпрограмм AJAX для приведения их в модель viewmodel. Нокаут не относится к AJAX, так как вы справляетесь с тем, что часть вашего приложения зависит от вас (но это обычно довольно просто).

В вашем вопросе вы ожидаете, что модель автоматически обновится, чтобы отобразить соответствующий элемент viewmodel. Это избыточно; неясно, что вам нужно что-то отдельное, которое просто копирует значение из режима просмотра. Модель просмотра может просто включать модель. Но если у вас есть больше возможностей для моделирования, так что вам нужно, чтобы ваши элементы модели собирались вместе в структуре, предложение Уилла Дженкинса об использовании subscribe является самым простым способом реагирования на изменения в модели viewmodel.

В комментариях ниже, Дженкинс выводит функции полезности. Нокаут обеспечивает преобразование между JSON и наблюдаемыми. Они также полезны для миграции назад и вперед между моделью и моделью просмотра.

Смотрите также: ko.mapping

+0

Это действительно означало бы, что Knockout не "модель в курсе".Как только вы вытащите модель с сервера, отредактируйте ее с помощью модели представления и хотите сохранить ее на сервере, это означает, что вам нужно переписать свою модель с нуля? Также мне приходится подписываться на прокси-сервер, чтобы обновить исходные эталонные звуки. – Ucodia

+0

Вам не нужно использовать подписку вообще, это немного анти-шаблон с нокаутом imo. Что касается круговых поездок на сервер, это легко - вы можете прямо перейти от json к вашему vm, а затем использовать служебную функцию, такую ​​как ko.toJSON, чтобы де-нокаутировать ваш vm, чтобы отправить его обратно. См. Здесь: http://knockoutjs.com/documentation/json-data.html –

+0

@Ucodia Я думаю, вы обнаружите, что Knockout проще, если вы не настаиваете на том, чтобы следовать примеру отдельной модели. Ваша модель находится на сервере. Вам просто нужно получить данные в своем приложении и записать данные из вашего приложения обратно на сервер. –

0

Причина, по которой не обновляется, потому что ваш settings.size не является наблюдаемой и ваш код не предусматривает использование в качестве settings.size размера, выбранного в HTML.

// default Model for settings 
function settings(){ 
    this.size = ko.observable(5); 
} 

// settings view model 
var settingsVM = function() {  
    return { 
     sizes: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 
     settings: new settings() 
    } 
}(); 

// subscribe to changes 
settingsVM.settings.size.subscribe(function() { 
    alert("model: " + settingsVM.settings.size()); 
}) 

ko.applyBindings(settingsVM); 

см обновлен скрипку here

Смежные вопросы