2012-10-07 53 views
7

Code:nguyên cảo bối cảnh sai này

export class ViewModel { 
     public users: knockout.koObservableArrayBase; 

     constructor() { 
      this.users = ko.observableArray([]); 
      this.removeUser = this.removeUser.bind(this);//<-- Here compiller shows error 
     } 

     removeUser(user: User): void { 
      this.users.remove(user); 
     } 
} 

Html:

<table> 
    <thead> 
     <tr> 
      <th>Name</th> 
      <th>Surname</th> 
     </tr> 
    </thead> 
    <tbody data-bind="foreach: users"> 
     <tr> 
      <td><a href="#" data-bind="click: $root.removeUser">Remove</a></td> 
      <td data-bind="text: name"></td> 
      <td data-bind="text: surname"></td> 
     </tr> 
    </tbody> 
</table> 

Vấn đề là trong phương pháp removeUser. Theo mặc định, nếu tôi không ràng buộc ngữ cảnh, thì đối tượng == UserToDelete - không phải viewModel này. Nếu tôi thêm vào hàm tạo: this.removeUser = this.removeUser.bind(this); (manually enforce context) thì ngữ cảnh là khi cần == viewmodel này, nhưng sau đó TypeScript than phiền cho "Không thể chuyển đổi hàm thành (người dùng: User) => void yêu cầu chữ ký cuộc gọi, nhưng Hàm thiếu một."

+0

Nếu bạn không ngại HTML lộn xộn, đây là giải pháp thay thế: Remove

Trả lời

5

Tôi không quen với ko nên có lẽ có cách tốt hơn để giải quyết chuyển ngữ cảnh, nhưng lỗi trình biên dịch bản ghi của bạn là do 'bind' trả về kiểu 'Hàm' không tương thích với kiểu 'removeUser' . Bạn sẽ có thể giải quyết điều này bằng cách đúc các chức năng trở thành loại chữ ký gốc như sau:

this.removeUser = <(user: User) => void> this.removeUser.bind(this); 
2

Vâng tôi đã có cùng một vấn đề Đó là lý do tôi đã đưa ra các lớp cơ sở sau đây để khắc phục vấn đề của tôi

export class ViewModelBase { 
    private prefix: string = 'On'; 

    public Initialize() { 
     for (var methodName in this) { 
      var fn = this[methodName]; 
      var newMethodName = methodName.substr(this.prefix.length); 
      if (typeof fn === 'function' && methodName.indexOf(this.prefix) == 0 && this[newMethodName] == undefined) { 
       this[newMethodName] = $.proxy(fn, this); 
      } 
     } 
    } 
} 

Điều này làm vòng lặp tất cả các thành viên trong lớp của bạn và nếu phương thức bắt đầu bằng Bật nó sẽ tạo phương thức mới mà không Bật sẽ gọi phương thức gốc với ngữ cảnh phù hợp.

Không phải là $.proxy là một cuộc gọi jquery để jquery là cần thiết để làm việc này.

1

Vâng, giải pháp đơn giản nhất và những gì tôi thường làm với kiểu chữ và loại bỏ js là tôi không khai báo các hàm được gọi là từ loại trực tiếp trên nguyên mẫu nhưng tại hàm tạo. Vì vậy, tôi sẽ làm như sau:

export class ViewModel { 
     public users: knockout.koObservableArrayBase; 
     removeUser:(user: User) => void; 

     constructor() { 
      this.users = ko.observableArray([]); 
      this.removeUser = (user:User) => { 
       this.users.remove(user); 
      } 
     } 
} 
0

Tôi đã gặp phải vấn đề tương tự. Để có được bối cảnh phù hợp, bạn có thể sử dụng các tham số được truyền bởi clickbinding. Clickbinding chuyển 2 tham số, tức là người dùng và sự kiện jquery của lần nhấp.

Nếu bạn thực hiện sự kiện jquery và sử dụng hàm ko.contextFor(), bạn có thể có được ngữ cảnh phù hợp.

Chức năng của bạn sẽ giống như thế:

removeUser(user: User, clickEvent: any): void { 
    var self = ko.contextFor(clickEvent.srcElement).$root; 
    self.users.remove(user); 
} 
2

Một cách khác là để thay đổi kích ràng buộc để sử dụng bind hàm JavaScript để buộc các giá trị của this là mô hình điểm của bạn: data-bind="click: $root.MyFunc.bind($root)".

Lưu ý rằng $data và đối tượng nhấp chuột event vẫn sẽ được thông qua tại như lập luận để MyFunc từ Knockout như mô tả của các đặc điểm kỹ thuật click binding. Nếu bạn cần ghi đè các đối số được chuyển đến MyFunc, chỉ cần chuyển chúng vào hàm liên kết sau $root như sau: .bind($root, param1, param2). Về mặt kỹ thuật, các đối số này sẽ là được thêm trước vào các đối số do Knockout cung cấp, cho các đối số [param1, param2, data, event].

Các vấn đề liên quan