2013-10-23 34 views
0

我想爲我的應用程序做一個基本視圖模型,但我努力訪問基本viewmodel的上下文。混亂的「這個」在揭示和durandal原型模式

這裏是我的基地視圖模型:

define(["config", 'services/logger'], function (config, logger) { 
    'use strict'; 
    var 
    app = require('durandal/app'), 
    baseViewModel = function() { 
     this.items = ko.observableArray(); 
     this.title = ko.observable(); 
     this.selectedItem = ko.observable(); 
    }; 
    baseViewModel.prototype = (function() { 
     var 
     populateCollection = function (initialData, model) { 
      var self = this; 
      if (_.isEmpty(self.items())) { 
       ko.utils.arrayForEach(initialData, function (item) { 
        // self here works for all extending modules such as users 
        self.items.push(new model(item)); 
       }); 
      } 
     }, 
     deleteItem = function (item) { 
      // "this" here same as prototype gives me window object :(
      // so removing never happes 
      this.items.remove(item); 
      logger.log(config.messages.userMessages.confirmDeleted(item.Name()), {}, '', true); 
     }, 
     confirmDelete = function (item) { 
      var 
      userMessage = config.messages.userMessages.confirmDelete(item.Type(), item.Name()), 
      negation = config.confirmationModalOptions.negation, 
      affirmation = config.confirmationModalOptions.affirmation; 

      app.showMessage(userMessage, 'Deleting ' + item.Type(), [affirmation, negation]).then(
       function (dialogResult) { 
        dialogResult === affirmation ? deleteItem(item) : false; 
       }); 
     }; 
     return { 
      populateCollection: populateCollection, 
      confirmDelete: confirmDelete, 
      deleteItem: deleteItem 
     } 
    })(); 
    return baseViewModel; 
}); 

我所在的地方使用這種非工作的事情的一個例子是:

define(['services/logger', 'models/user', 'viewmodels/baseviewmodel', 'services/dataservice'], function (logger, user, baseviewmodel, dataservice) { 
    var 
    users = new baseviewmodel(); 
    users.title('Users') 
    users.searchTerm = ko.observable().extend({ persist: users.title() + '-searchterm' }); 
    users.activate = function() { 
     this.populateCollection(dataservice.getUsers, user.model); 
    } 
    return users; 
}); 

項目也開始使用populateCollection無誤。 confirmDelete也在模板中正確綁定,這可能是由於不需要上下文 ,但deleteItem需要上下文,因此它可以訪問items並在其上調用remove

如何正確地訪問this爲一體的baseViewModel 這樣我就可以輕鬆地引用它在我的方法與此模式的背景下?

非常感謝

+0

你的觀點是不是在這裏,但我希望你在這個使用類似選項4帖子:http://stackoverflow.com/a/8707661/1641941由於這隻附加一個處理程序,並根據'event.target'委託給正確的函數。不知道淘汰賽,但這與任何需要點擊的項目列表相關。最好不要在物品上附加處理程序,而是在容器上附加處理程序。 – HMR

回答

1

編輯:看起來也許this未在deleteItem正確綁定,因爲它被稱爲在confirmDelete內的回調。所以試試這個片段在您的原始模型

confirmDelete = function (item) { 
     var self=this, 
     userMessage = config.messages.userMessages.confirmDelete(item.Type(), item.Name()), 
     negation = config.confirmationModalOptions.negation, 
     affirmation = config.confirmationModalOptions.affirmation; 

     app.showMessage(userMessage, 'Deleting ' + item.Type(), [affirmation, negation]).then(
      function (dialogResult) { 
       dialogResult === affirmation ? self.deleteItem.call(self,item) : false; 
      }); 
    }; 

orrr,我的其他解決方案。

我從來沒有使用之前的「露出原型模式」,所以這裏是如何做到這一點不堅持,無論是我們的理解:)

的模式我宣佈一切,我的視圖模型和使用的屬性var self = this,這是非常明確的,我所有的代碼都做了。這是您的基本模型,重寫。如果所有viewmodel邏輯都封裝在視圖模型中,並且viewmodel在構造函數/函數定義中聲明它的依賴關係,通常會很有幫助。

baseViewModel = function (dataService,userModel) { 
    var self = this; 
    self.items = ko.observableArray(); 
    self.title = ko.observable(); 
    self.searchTerm = ko.observable().extend({ persist: self.title() + '-searchterm' }); 
    self.selectedItem = ko.observable(); 

    self.populateCollection = function (initialData, model) { 
     if (_.isEmpty(self.items())) { 
      ko.utils.arrayForEach(initialData, function (item) { 
       // self here works for all extending modules such as users 
       self.items.push(new model(item)); 
      }); 
     } 
    }; 

    self.activate = function() { 
     this.populateCollection(dataservice.getUsers, userModel); 
    } 

    self.deleteItem = function (item) { 
     // "this" here same as prototype gives me window object :(
     // so removing never happes 
     self.items.remove(item); 
     logger.log(config.messages.userMessages.confirmDeleted(item.Name()), {}, '', true); 
    }; 

    self.confirmDelete = function (item) { 
     var 
     userMessage = config.messages.userMessages.confirmDelete(item.Type(), item.Name()), 
     negation = config.confirmationModalOptions.negation, 
     affirmation = config.confirmationModalOptions.affirmation; 

     app.showMessage(userMessage, 'Deleting ' + item.Type(), [affirmation, negation]).then(
      function (dialogResult) { 
       dialogResult === affirmation ? self.deleteItem(item) : false; 
      }); 
    }; 
}; 

注意,因爲我也動了你的依賴複製到視圖模型構造,現在你的初始化代碼如下所示:

define(['services/logger', 'models/user', 'viewmodels/baseviewmodel', 'services/dataservice'], function (logger, user, baseviewmodel, dataservice) { 
    var users = new baseviewmodel(dataservice,user.model); 
    users.title('Users') 
    return users; 
}); 
+1

愛第一句話,我們都不明白的模式:)大聲笑我知道這一個伴侶,我將退出其中的一些,所以需要節省內存和原型將保持共享的內存中的一種方法,所以對我來說差別很大。雖然 – XGreen

+0

增加了一個從閱讀代碼更徹底的想法,請檢查出來。 – scaryman

+0

這個想法看起來很有趣,今天我試圖通過從populateCollection代替confirmDelete來傳遞自己,但導致另一個擴展器的模塊在刪除後有錯誤的項目。明天再試試,回覆你 – XGreen