2013-07-17 42 views
1

簡單的問題,很確定這是一個複雜的答案:)durandal(HotTowel)視圖模型的繼承?

是否有可能實現Durandal視圖模型的某種形式的繼承?

所以,如果你有一個視圖模型是這樣的:

define(['durandal/app', 'services/datacontext', 'durandal/plugins/router', 'services/logger'], 
    function (app, datacontext, router, logger) { 
     var someVariable = ko.observable(); 
     var isSaving = ko.observable(false); 

     var vm = { 
      activate: activate, 
      someVariable : someVariable, 
      refresh: refresh, 
      cancel: function() { router.navigateBack(); }, 
      hasChanges: ko.computed(function() { return datacontext.hasChanges(); }), 
      canSave: ko.computed(function() { return datacontext.hasChanges() && !isSaving(); }), 
      goBack: function() { router.navigateBack(); }, 
      save: function() { 
       isSaving(true); 
       return datacontext.saveChanges().fin(function() { isSaving(false); }) 
      }, 
      canDeactivate: function() { 
       if (datacontext.hasChanges()) { 
        var msg = 'Do you want to leave and cancel?'; 
        return app.showMessage(msg, 'Navigate Away', ['Yes', 'No']) 
         .then(function(selectedOption) { 
          if (selectedOption === 'Yes') { 
           datacontext.cancelChanges(); 
          } 
          return selectedOption; 
         }); 
       } 
       return true; 
      } 
     }; 

     return vm; 

     //#region Internal Methods 
     function activate(routeData) { 
      logger.log('View Activated for id {' + routeData.id + '}, null, 'View', true); 
      }); 
     } 
     //#endregion 

     function refresh(id) { 
      return datacontext.getById(client, id); 
     } 
    }); 

是否有可能作出這樣陷入某種基本類型,並從它繼承進一步的ViewModels,能夠延長要求清單等?

還有另外一個問題,但視圖模型看起來與我爲durandal/HotTowel構建的視圖模型不太一樣。

謝謝。

回答

2

基於你的說法,我想出了這個。讓我知道如果這對你有用,如果它沒有,那麼讓我知道我做錯了什麼。

謝謝。

viewmodelBase

define(['durandal/app', 'services/datacontext', 'durandal/plugins/router', 'services/logger'], 
    function (app, datacontext, router, logger) { 
     var vm = function() { 
      var self = this; 
      this.someVariable = ko.observable(); 
      this.isSaving = ko.observable(false); 
      this.hasChanges = ko.computed(function() { return datacontext.hasChanges(); }); 
      this.canSave = ko.computed(function() { return datacontext.hasChanges() && !self.isSaving(); }); 
     }; 

     vm.prototype = { 
      activate: function (routeData) { 
       logger.log('View Activated for id {' + this.routeData.id + '}', null, 'View', true); 
      }, 
      refresh: function (id) { 
       return datacontext.getById(client, id); 
      }, 
      cancel: function() { 
       router.navigateBack(); 
      }, 
      goBack: function() { router.navigateBack(); }, 
      save: function() { 
       var self = this; 
       this.isSaving(true); 
       return datacontext.saveChanges().fin(function() { self.isSaving(false); }) 
      }, 
      canDeactivate: function() { 
       if (datacontext.hasChanges()) { 
        var msg = 'Do you want to leave and cancel?'; 
        return app.showMessage(msg, 'Navigate Away', ['Yes', 'No']) 
         .then(function(selectedOption) { 
          if (selectedOption === 'Yes') { 
           datacontext.cancelChanges(); 
          } 
          return selectedOption; 
         }); 
       } 
       return true; 
      } 
     }; 

     return vm; 
    }); 

父視圖模型

define([viewmodelBase], function (vmbase) { 
    var vm1 = new vmbase(); 
    vm1.newProperty = "blah"; 
    var vm2 = new vmbase(); 
}); 
+0

嗨埃文。道歉我還沒有回到這個這麼久。題;在你的方法上,你能擴展注入的服務嗎?因此,在你的基地,你有應用程序,的datacontext等,在孩子[viewModelBase。你可以簡單的擴展,與([viewModelBase],「服務/服務1」,「服務/服務2」,函數(vmbase,服務1,serivce2)? – Adam

+0

用JavaScript有各類圍繞着如何做的遺傳模式。他們都有他們的好處和一些比其他更復雜我只是谷歌JavaScript原型繼承,並找到適合您的方案的解決方案。 –

2

我敢肯定,這可以用jQuery的擴展方法來實現。這只是發生在我身上,所以有可能是我想的東西,但一個基本的例子是沿着線的東西:

basevm.js

... your mentioned viewmodel 

inheritingvm.js

define(['basevm'], function (basevm) { 
    var someNewObservable = ko.observable(); 

    var vm = $.extend({ 
     someNewObservable : someNewObservable 
    }, basevm); 

    return vm; 
}); 

請讓我知道這是否工作。我只是從頭頂編碼,並沒有經過測試。

+1

我可以證實這個工程。好的! – opp

+0

嗨,對不起,我已經花了這麼長時間回來但這並不意味着基本上每個使用這種技術的視圖模型都會共享一個basevm嗎?我對durandal的理解是,像這樣注入的模型將會有單一生命週期嗎?我可能會關雖然,謝謝! – Adam

+0

據我所知,這將有一個單身一生,是的。 –

1

我在博客上寫了一篇文章解決了這個問題。簡而言之,我在我的一個項目中爲我的所有模態對話框視圖使用原型繼承。這裏是我寫的帖子(可以跳到代碼部分)link以及演示它的jsFiddle example

簡化的例子,可以在工作迪朗達爾(注意:在各視圖模型返回它的構造函數,而不是一個對象):

的ViewModels/modal.js

define(['durandal/system'], 
function(system) { 
    var modal = function() { 
    this.name = 'Modal'; 
    } 

    modal.prototype = { 
    activate: function() { 
     system.log(this.name + ' activating'); 
    }, 
    attached: function(view) { 
     system.log(this.name + ' attached'); 
    }, 
    deactivate: function() { 
     system.log(this.name + ' deactivating'); 
    }, 
    detached: function(view, parent) { 
     system.log(this.name + ' detached'); 
    } 
    }; 

    return modal; 
}); 

的ViewModels /子.js

define(['durandal/system', 'viewmodels/modal'], 
function(system, Modal) { 
    var child = function() { 
    this.name = 'Child Modal'; 
    } 

    // inherits from Modal 
    child.prototype = new Modal(); 
    child.prototype.constructor = child; 
    child.prototype._super = Modal.prototype; 

    // overrides Modal's activate() method 
    child.prototype.activate = function() { 
    this._super.activate.call(this); // we can still call it from the _super property 
    system.log(this.name + ' activating [overridden version]'); 
    }; 

    return child; 
}); 

我更喜歡這個實現,因爲它支持代碼重用,儘可能符合OOP原則,並允許我在需要時通過_super屬性調用基類的方法。您可以根據需要輕鬆轉換。