2012-03-06 23 views
185

Trong knock-out js Tôi thấy Xem Models khai báo là một trong hai:Sự khác nhau giữa loại trực tiếp Xem Models tuyên bố là dạng đối tượng vs chức năng

var viewModel = { 
    firstname: ko.observable("Bob") 
}; 

ko.applyBindings(viewModel); 

hay:

var viewModel = function() { 
    this.firstname= ko.observable("Bob"); 
}; 

ko.applyBindings(new viewModel()); 

sự khác biệt giữa hai là gì, nếu có ?

Tôi đã tìm thấy this discussion trên nhóm nhạc knockoutjs google nhưng nó không thực sự mang lại cho tôi câu trả lời thỏa đáng.

tôi có thể thấy một lý do nếu tôi muốn khởi tạo mô hình với một số dữ liệu, ví dụ:

var viewModel = function(person) { 
    this.firstname= ko.observable(person.firstname); 
}; 

var person = ... ; 
ko.applyBindings(new viewModel(person)); 

Nhưng nếu tôi không làm điều đó thì nó có vấn đề mà phong cách tôi chọn?

+0

Tôi không tin có sự khác biệt. Tôi thường sử dụng mẫu hàm tạo, vì tôi thường có các phương thức mà tôi muốn khai báo trên 'prototype' (các phương thức thường, ví dụ, lấy dữ liệu từ máy chủ và cập nhật mô hình khung sao cho phù hợp). Tuy nhiên, bạn vẫn có thể tuyên bố rõ ràng chúng như là một tài sản của một đối tượng theo nghĩa đen, vì vậy tôi không thể thấy sự khác biệt. –

+4

Điều này không liên quan gì đến loại trực tiếp, và mọi thứ cần làm với việc dễ dàng tạo ra các đối tượng tùy chỉnh trong JavaScript – zzzzBov

+1

@Kev nếu viewModel là hàm dựng mà bạn viết nó trong UpperCase giống như var PersonViewModel = function() {...} ; – Elisabeth

Trả lời

242

Có một số lợi thế khi sử dụng chức năng để xác định kiểu xem của bạn.

Ưu điểm chính là bạn có quyền truy cập ngay vào giá trị this bằng với trường hợp được tạo. Điều này có nghĩa rằng bạn có thể làm:

var ViewModel = function(first, last) { 
    this.first = ko.observable(first); 
    this.last = ko.observable(last); 
    this.full = ko.computed(function() { 
    return this.first() + " " + this.last(); 
    }, this); 
}; 

Vì vậy, quan sát tính của bạn có thể bị ràng buộc để các giá trị thích hợp của this, thậm chí nếu gọi từ một phạm vi khác nhau.

Với một đối tượng theo nghĩa đen, bạn sẽ phải làm:

var viewModel = { 
    first: ko.observable("Bob"), 
    last: ko.observable("Smith"), 
}; 

viewModel.full = ko.computed(function() { 
    return this.first() + " " + this.last(); 
}, viewModel); 

Trong trường hợp đó, bạn có thể sử dụng viewModel trực tiếp trong quan sát được tính toán, nhưng nó không nhận được đánh giá ngay lập tức (theo mặc định), do đó bạn không thể xác định nó bên trong đối tượng theo nghĩa đen, như viewModel không được xác định cho đến sau khi đối tượng theo nghĩa đen đã đóng. Nhiều người không thích rằng việc tạo mô hình xem của bạn không được gói gọn thành một cuộc gọi.

Một mẫu khác mà bạn có thể sử dụng để đảm bảo rằng this luôn thích hợp là đặt biến trong hàm bằng giá trị thích hợp this và sử dụng nó thay thế. Đây sẽ là như sau:

var ViewModel = function() { 
    var self = this; 
    this.items = ko.observableArray(); 
    this.removeItem = function(item) { 
     self.items.remove(item); 
    } 
}; 

Bây giờ, nếu bạn đang ở trong phạm vi của một mục cá nhân và gọi $root.removeItem, giá trị của this sẽ thực sự được các dữ liệu bị ràng buộc ở cấp đó (đó sẽ là mục). Bằng cách sử dụng bản thân trong trường hợp này, bạn có thể đảm bảo rằng nó đang được xóa khỏi mô hình chế độ xem tổng thể.

Một tùy chọn khác đang sử dụng bind, được hỗ trợ bởi trình duyệt hiện đại và được KO thêm vào, nếu nó không được hỗ trợ. Trong trường hợp đó, nó sẽ trông giống như:

var ViewModel = function() { 
    this.items = ko.observableArray(); 
    this.removeItem = function(item) { 
     this.items.remove(item); 
    }.bind(this); 
}; 

Có nhiều hơn nữa có thể được nói về chủ đề này và nhiều mẫu mà bạn có thể khám phá (giống như kiểu mô-đun và mô hình mô-đun tiết lộ), nhưng về cơ bản cách sử dụng một chức năng cho phép bạn linh hoạt hơn và kiểm soát đối tượng được tạo ra và khả năng tham chiếu các biến riêng tư với cá thể đó.

+1

Câu trả lời hay. Tôi thường sử dụng một hàm (sử dụng mô hình mô-đun tiết lộ) cho các đối tượng phức tạp như dạng xem. Nhưng đối với các mô hình đơn giản, tôi sử dụng một hàm để tôi có thể xử lý mọi thứ ở một nơi. –

+1

@JohnPapa - vừa xem video PluralSight của bạn về loại trực tiếp (chỉ hơn một nửa - và, tình cờ, chỉ xem phần về đối tượng theo nghĩa đen so với hàm). Thực sự làm tốt và đã giúp giảm đồng xu. Cũng đáng giá một tháng đăng ký cho rằng một mình. – Kev

+0

@Kev - Cảm ơn. Vui vì bạn đang nhận được giá trị của nó. Một số sẽ không quan tâm đến mô-đun đó vì nó không thực sự là một khái niệm Knockout, nhiều mẫu JavaScript hơn. Nhưng tôi tìm thấy khi tôi tiếp tục với Knockout rằng những khái niệm đó thực sự đã giúp tôi tạo ra mã sạch hơn. Dù sao, vui mừng bạn thích nó :) –

12

tôi sử dụng một phương pháp khác nhau, mặc dù tương tự:

var viewModel = (function() { 
    var obj = {}; 
    obj.myVariable = ko.observable(); 
    obj.myComputed = ko.computed(function() { return "hello" + obj.myVariable() }); 

    ko.applyBindings(obj); 
    return obj; 
})(); 

Couple lý do:

  1. Không sử dụng this, mà có thể nhầm lẫn khi sử dụng trong vòng ko.computed s vv
  2. My ViewModel là một singleton, tôi không cần tạo nhiều phiên bản (ví dụ: new viewModel())
+0

Đây là mô hình mô-đun tiết lộ nếu không nhầm lẫn. Câu trả lời hay nhưng câu hỏi không phải là về mô hình này. – Phil

+0

@paul: Xin lỗi vì đã yêu cầu chuỗi cũ. u nói 'My viewModel là một singleton, tôi không cần phải tạo ra nhiều trường hợp (tức là new viewModel())' nhưng nó không phải là rõ ràng những gì u đang cố gắng để nói 'Tôi không cần phải tạo nhiều trường hợp' u có thể plzz đi kèm với sử dụng nhiều hơn để người ta có thể hiểu được lợi thế của cách tiếp cận của bạn. cảm ơn – Mou

+0

IMO, một trong những lý do bạn khai báo ViewModel là 'hàm' là vì bạn sẽ thực thi nó nhiều lần. Tuy nhiên, trong ví dụ của tôi về, nó là một hàm ẩn danh được gọi ngay lập tức, vì vậy nó sẽ không được tạo nhiều hơn một lần. Nó rất giống với Object Literal trong ví dụ trên, nhưng cho bạn nhiều sự cô lập hơn – paulslater19

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