2013-05-15 12 views
19

Używam Knockout.js do wielu projektów ostatnio i piszę dużo powtarzalnego kodu. Chciałbym móc zdefiniować klasę BaseViewModel i dziedziczyć z niej moje ViewModels specyficzne dla strony. Nie wiem, jak to zrobić, to JavaScript. Tu jest mój podstawowy BaseViewModel:Knockout ViewModel klasa bazowa, dziedziczenie JavaScriptu

(function (ko, undefined) { 
    ko.BaseViewModel = function() { 
     var self = this; 
     self.items = ko.observable([]); 
     self.newItem = {}; 
     self.dirtyItems = ko.computed(function() { 
      return self.items().filter(function (item) { 
       return item.dirtyFlag.isDirty(); 
      }); 
     }); 
     self.isDirty = ko.computed(function() { 
      return self.dirtyItems().length > 0; 
     }); 
     self.load = function() { } 
    }; 
}(ko)); 

Chciałbym móc listy podpisów do metod takich jak load w BaseViewModel a następnie dać im definicje w dziedziczy ViewModel. Czy to możliwe? Znalazłem kilka rozwiązań online, ale wszystkie one polegają na definiowaniu funkcji/klas, aby dziedziczenie działało.

+0

dlaczego przekazujesz 'niezdefiniowane' do funkcji? – Tyrsius

+0

http://programmers.stackexchange.com/a/158376/90240 – gwely

+0

Huh, nigdy wcześniej tego nie widziałem. Nigdy też nie natknąłem się na przypadek, w którym to nie powoduje błędu i nie wyjaśnia, co to jest. – Tyrsius

Odpowiedz

17

Od swojej BaseViewModel jest tylko dodanie wszystkich właściwości/metod this (a nie przy użyciu prototyp), to jest całkiem proste:

W nowych modelach widoku, po prostu zadzwoń BaseViewModel:

var MyVM = function() { 
    var self = this; 
    ko.BaseViewModel.call(self); 

    self.somethingElse = ko.observable(); 
    self.itemCount = ko.computed(function() { return self.items().length; }); 
    self.items([1, 2, 3]); 
}; 


// ... 
var vm = new MyVM(); 
+0

To jest znacznie łatwiejsze niż się spodziewałem. Teraz muszę tylko dowiedzieć się, jak to działa! – gwely

+0

Linia 'ko.BaseViewModel.call (self)' jest taka sama jak wykonanie ': base()' w języku C#, prawda? – gwely

+1

@theyshookhands Tak, jest to to samo co wywołanie ': base()'. 'ViewModel.prototype = new BaseViewModel()' jest taki sam jak 'Class: SubClass' w języku C#. – Tyrsius

10

Dziedziczenie JavaScriptu odbywa się w dwóch częściach. Pierwszy znajduje się w konstruktorze, a drugi na prototypie (którego nie używasz, więc możesz pominąć).

var ViewModel = function(data) { 
    BaseViewModel.call(this); 
}; 
//you only need to do this if you are adding prototype properties 
ViewModel.prototype = new BaseViewModel(); 

Do ostatniego punktu, o przesłanianie load jej nie różni się, że umieszczenie load funkcji na viewmodel normalnie. JavaScript pozwala na zastąpienie dowolnych właściwości obiektów dowolnymi, tutaj nie ma specjalnych kroków.

Oto dziedziczenie fiddle demonstrating.

+0

Jeśli potrzebujesz jedynie wsparcia nowoczesnych przeglądarek, możesz zastąpić ostatnią linię przez 'Viewmodel.prototype = Object.create (BaseViewModel.prototype);' i uniknąć pewnych drażliwych problemów z wszelkimi niepożądanymi efektami wywołania 'BaseViewModel' w tym droga. – Brandon

+0

Łatwo jest przesłonić 'Object.create' w starszych przeglądarkach:' var objCreate = Object.create || funkcja (o) {funkcja F() {}; F.prototype = o; return new F(); }; ' –

Powiązane problemy