2014-01-08 27 views
4

使用視圖模型時,「本」的問題請參閱以下更新的代碼的打字稿及淘汰賽

我試圖用基因敲除與打字稿,但似乎我不能到我的打字稿視圖模型綁定我的看法...看來我與this一個問題,但我不明白爲什麼...

this.UserList調用Fill方法

這裏的時候是不確定的是我的視圖模型:

module ViewModels { 
    export class UserViewModel { 

     constructor() { 
      this.UserList = ko.observableArray<KnockoutObservable<Models.User>>([]); 

      this.RemoveItem = <(user: KnockoutObservable<Models.User>) => void> this.RemoveItem.bind(this); 
      this.AcceptItem = <(user: Models.User) => void> this.AcceptItem.bind(this); 
      this.AddItem = <() => void> this.AddItem.bind(this); 
     } 

     public UserList: KnockoutObservableArray<KnockoutObservable<Models.User>>; 
     public Fill() { 
      $.ajax({ 
       type: "POST", 
       url: "/Guest/LoadGuest/", 
       success: data=> { 
        $(data).each((index: any, item)=> { 
         var guest = new Models.User(); 
         guest.FirstName = ko.observable(item.firstName); 
         guest.LastName = ko.observable(item.lastName); 
         guest.IsNew = ko.observable(false); 
         this.UserList.push(ko.observable(guest)); 
        }); 
       } 
      }); 
     } 

     public AddItem() { 
      var guest = new Models.User(); 
      guest.FirstName = ko.observable(""); 
      guest.LastName = ko.observable(""); 
      guest.IsNew = ko.observable(true); 

      this.UserList.push(ko.observable(guest)); 
     } 

     public AcceptItem(user: Models.User) { 
      user.IsNew = ko.observable(false); 
     } 


     public RemoveItem(user: KnockoutObservable<Models.User>) { 
      this.UserList.remove(user); 
     } 


    } 
} 

這是我的觀點:

<table> 
    <thead> 
     <tr><th>Prénom</th><th>Nom de famille</th></tr> 
    </thead> 
    <tbody data-bind="foreach: UserList"> 
     <tr data-bind="if:IsNew"> 
      <td><input type="text" data-bind="text: FirstName" /></td> 
      <td><input type="text" data-bind="text: LastName" /></td> 
      <td><a data-bind="click:$parent.AcceptItem">OK</a><a data-bind="click:$parent.RemoveItem">Annuler</a></td> 
     </tr> 
     <tr data-bind="if:!IsNew"> 
      <td data-bind="text: FirstName"></td> 
      <td data-bind="text: LastName"></td> 
      <td></td> 
     </tr> 
    </tbody> 
</table> 
<a id="AddGuest" data-bind="click:AddItem">Add</a> 

@section scripts{ 
    <script src="~/Scripts/models/ModelBase.js"></script> 
    <script src="~/Scripts/models/User.js"></script> 
    <script src="~/Scripts/viewmodels/UserViewModel.js"></script> 
    <script> 

     var vm = new ViewModels.UserViewModel(); 
     vm.Fill(); 
     ko.applyBindings(vm); 
    </script> 

} 

這裏是我的模型:

module Models{ 

    export class User extends Models.ModelBase { 
     constructor() { 
      super(); 

     } 

     public FirstName: KnockoutObservable<string>; 
     public LastName: KnockoutObservable<string>; 
     public Age: KnockoutObservable<Age>; 
    } 

    export class Age { 
     public ID: KnockoutObservable<number>; 
     public Description: KnockoutObservable<string>; 
    } 
} 

新的工作代碼幫助旨意:

視圖模型:

module ViewModels { 
    export class UserViewModel { 
     constructor() { 

     } 

     public UserList: KnockoutObservableArray<Models.User> = ko.observableArray<Models.User>([]); 
     public Fill =() => { 
      $.ajax({ 
       type: "POST", 
       url: "/Guest/LoadGuest/", 
       success: data=> { 
        for (var i = 0; i < data.length; i++) { 
         var item = data[i]; 
         var guest = new Models.User(); 
         guest.FirstName(item.firstName); 
         guest.LastName(item.lastName); 
         guest.Age().Description("Test Age"); 
         guest.IsNew(false); 
         this.UserList.push(guest); 
        } 
       } 
      }); 
     } 

     public AddItem =() => { 
      var guest = new Models.User(); 
      guest.FirstName = ko.observable(""); 
      guest.LastName = ko.observable(""); 
      guest.IsNew(true); 
      this.UserList.push(guest); 

     } 

     public AcceptItem = (user: Models.User) => { 
      user.IsNew(false); 
     } 

     public RemoveItem = (user: Models.User) => { 
      this.UserList.remove(user); 
     } 

    } 
} 

型號:

module Models{ 

    export class ModelBase{ 
     constructor() { 
      this.IsNew = ko.observable(false); 
     } 
     public IsNew: KnockoutObservable<boolean>; 
    } 

    export interface IUser { 
     FirstName: KnockoutObservable<string>; 
     LastName: KnockoutObservable<string>; 
     Age: KnockoutObservable<Age>; 
    } 


    export class User extends Models.ModelBase implements IUser { 
     constructor() { 
      super(); 
      this.FirstName = ko.observable(""); 
      this.LastName = ko.observable(""); 
      this.Age = ko.observable(new Age()); 
     } 

     public FirstName: KnockoutObservable<string>; 
     public LastName: KnockoutObservable<string>; 
     public Age: KnockoutObservable<Age>; 
    } 

    export class Age { 
     constructor() { 
      this.ID = ko.observable(null); 
      this.Description = ko.observable(""); 
     } 

     public ID: KnockoutObservable<number>; 
     public Description: KnockoutObservable<string>; 
    } 
} 

查看:

<table> 
     <thead> 
      <tr><th>Prénom</th><th>Nom de famille</th><th>Age</th></tr> 
     </thead> 
     <tbody data-bind="foreach: UserList"> 
      <tr data-bind="ifnot:$data.IsNew"> 
       <td data-bind="text: FirstName"></td> 
       <td data-bind="text: LastName"></td> 
       <td data-bind="text: Age().Description"></td> 
      </tr> 
      <tr data-bind="if:$data.IsNew"> 
       <td><input type="text" data-bind="value: FirstName" /></td> 
       <td><input type="text" data-bind="value: LastName" /></td> 
       <td><input type="text" data-bind="value: Age().Description" /></td> 
       <td><a data-bind="click:$root.AcceptItem">OK</a><a data-bind="click:$root.RemoveItem">Annuler</a></td> 
      </tr> 
     </tbody> 
</table> 


    <a id="AddGuest" data-bind="click:AddItem">Add</a> 
@section scripts{ 
    <script src="~/Scripts/models/ModelBase.js"></script> 
    <script src="~/Scripts/models/User.js"></script> 
    <script src="~/Scripts/viewmodels/UserViewModel.js"></script> 
    <script> 
     var vm = new ViewModels.UserViewModel(); 
     vm.Fill(); 
     ko.applyBindings(vm); 
    </script> 

} 

回答

9

如果你想this被綁定到UserViewModel是那麼也許使用這種方法:

module ViewModels { 
    export class UserViewModel { 

     UserList: KnockoutObservableArray<KnockoutObservable<Models.User>> = ko.observableArray<KnockoutObservable<Models.User>>([]); 

     Fill =() => { 
      $.ajax({ 
       type: "POST", 
       url: "/Guest/LoadGuest/", 
       success: data => { 
        $(data).each((index: any, item)=> { 
         var guest = new Models.User(); 
         guest.FirstName = ko.observable(item.firstName); 
         guest.LastName = ko.observable(item.lastName); 
         guest.IsNew = ko.observable(false); 
         this.UserList.push(ko.observable(guest)); 
        }); 
       } 
      }); 
     } 

     AddItem =() => { 
      var guest = new Models.User(); 
      guest.FirstName = ko.observable(""); 
      guest.LastName = ko.observable(""); 
      guest.IsNew = ko.observable(true); 

      this.UserList.push(ko.observable(guest)); 
     } 

     AcceptItem = (user: Models.User) => { 
      user.IsNew = ko.observable(false); 
     } 


     RemoveItem = (user: KnockoutObservable<Models.User>) => { 
      this.UserList.remove(user); 
     } 
    } 
} 

這裏的打字稿操場demo

您可以閱讀方法的說明,這裏所用:http://blogs.msdn.com/b/typescript/archive/2013/08/06/announcing-0-9-1.aspx(檢查「更好‘這個’處理)

順便說一下,我懷疑你在哪裏有KnockoutObservable<Models.User>你實際上應該有Models.User,當你有this.UserList.push(ko.observable(guest));你實際上應該有this.UserList.push(guest);。如果我錯過了某些東西,我還沒有更改代碼示例。

+0

謝謝你!你是對的,在打字稿和淘汰賽中有一些我不明白的概念。問題不是這個,而是更多的東西。我添加了新的工作代碼,以幫助新用戶。 – Hemadeus

+0

沒問題 - 樂於幫忙! –

1

的原因是你 '這' 指的是一個新的環境時,你是個夠方法中。爲了維持的意義「這個」,你可以用這樣的自變量,以進一步引用下來的樹 -

module ViewModels { 
    export class UserViewModel { 
     constructor() { 
      var self = this; 
      self.UserList = ko.observableArray<KnockoutObservable<Models.User>>([]); 

      self.RemoveItem = <(user: KnockoutObservable<Models.User>) => void> this.RemoveItem.bind(this); 
      self.AcceptItem = <(user: Models.User) => void> this.AcceptItem.bind(this); 
      self.AddItem = <() => void> this.AddItem.bind(this); 
     } 

     public UserList: KnockoutObservableArray<KnockoutObservable<Models.User>>; 
     public Fill() { 
      var self = this; 
      $.ajax({ 
       type: "POST", 
       url: "/Guest/LoadGuest/", 
       success: data=> { 
        $(data).each((index: any, item)=> { 
         var guest = new Models.User(); 
         guest.FirstName = ko.observable(item.firstName); 
         guest.LastName = ko.observable(item.lastName); 
         guest.IsNew = ko.observable(false); 
         self.UserList.push(ko.observable(guest)); 
        }); 
       } 
      }); 
     } 


    } 
} 
+0

我明白你的意思,但我不認爲它把任何感覺放到構造函數中,因爲在構造函數中我們處於相同的上下文中。但在填充方法中,我完全同意。我確實有其他問題,所以讓我檢查 – Hemadeus

+0

它不起作用,'self'對應於'Window' ...是否因爲從視圖調用了Fill()? – Hemadeus

+0

我不是TypeScript專家,但看看它是否會讓你定義var self = this;在視圖模型級而不是在方法內部。 –

3

使用lamda語法。

只需改變這一行

public Fill() {

這樣:

public Fill =() => {

在我們的代碼庫,我發現我實際上從未需要訴諸var self = this;解決方法。

其他建議:

1)如果你改變你的函數中使用的λ語法,你可以擺脫所有這些業務的:

 this.RemoveItem = <(user: KnockoutObservable<Models.User>) => void> this.RemoveItem.bind(this); 
     this.AcceptItem = <(user: Models.User) => void> this.AcceptItem.bind(this); 
     this.AddItem = <() => void> this.AddItem.bind(this); 

2)只是初始化,你宣佈你的公共屬性他們 - 這是一個很大的冗餘代碼做到這一點在構造函數(即同上)

相反的:

public UserList: KnockoutObservableArray<KnockoutObservable<Models.User>>; 

只是這樣做:

public UserList = ko.ObservableArray<Modesl.User>([]); 

UsersList對象仍然是強類型,你就不會需要這個線在構造函數:this.UserList = ko.observableArray<Models.User>([]);請注意,我用另一個海報,你可能不同意實際上想要一個observable array of observables,所以爲了清晰起見,我刪除了這個怪異的東西。

6

這裏的其他答案假設您對問題的描述是準確的。我決定實際測試你的代碼。以下是我發現的:

  1. 錯誤each功能。

    這可能在技術上有效,但它應該是針對DOM節點的。你應該使用$.each

    $.each(data, (index: any, item)=> { 
    
  2. 將視圖模型對象包裝在observable中。

    this.UserList.push(ko.observable(guest)); 
    

    這打破了你的RemoveItem函數。你應該只添加對象。

    this.UserList.push(guest); 
    
  3. 改寫observable而不是設置observable。

    user.IsNew = ko.observable(false); 
    

    敲除將無法看到這裏的變化。您需要設置observable。

    user.IsNew(false); 
    
  4. 使用<input>元素的錯誤綁定。

    <td><input type="text" data-bind="text: FirstName" /></td> 
    

    text綁定是單向的。您需要使用value

    <td><input type="text" data-bind="value: FirstName" /></td> 
    
  5. 在表達式中不當使用observable。

    <tr data-bind="if:!IsNew"> 
    

    此測試,如果觀察到的本身是false,它始終不是(因爲它是一個函數)。您想要測試觀察值的值是否爲false!IsNew()。更好的是,只需使用ifnot綁定即可。

    <tr data-bind="ifnot:IsNew"> 
    
+0

嗨thx有關observable和ifnot的信息,我不知道ifnot綁定。這是我對Stylist和淘汰賽的第一次測試,將其實施到我們的新項目中。 – Hemadeus

+0

哇人,史詩代碼審查,做得好! :) – Rocklan

1

如果更改MyFunc() { }你的函數的簽名是在lambda形式MyFunc =() => { }被接受的答案的建議,你會發現,你的功能不再爲你的類共享原型的功能,但而是作爲類的每個實例的函數變量複製。

另一種方法是改變點擊結合使用JavaScript的bind函數強制的this的價值是你的視圖模型:data-bind="click: $root.MyFunc.bind($root)"

注意$data和點擊event對象仍將被作爲參數從淘汰賽由click binding說明書中描述的傳遞給MyFunc。如果您需要覆蓋傳遞給MyFunc的參數,只需在$root之後將它們傳遞到綁定函數,如下所示:.bind($root, param1, param2)。從技術上講,這些參數將被加上給由Knockout提供的參數,給出參數[param1, param2, data, event]