2012-06-28 23 views
5

Tôi đang cố gắng triển khai Ứng dụng một trang dựa trên MVVM và hiện đang sử dụng khung Knockout.js để xử lý phần viewmodel/view của MVVM. Tôi đang bối rối mặc dù, như mọi ví dụ tôi đã nhìn vào để thực hiện Knockout liên quan đến việc tiết kiệm một viewmodel toàn bộ cơ sở dữ liệu. Không phải là những ví dụ này thiếu một "mô hình" bước, nơi viewmodel đồng bộ với mô hình lớp dữ liệu và mô hình không xác nhận/đồng bộ hóa máy chủ.MVVM với Knockout.js

Tôi muốn có nhiều mẫu/lượt xem khác nhau trên mỗi trang với mỗi chế độ xem khác nhau. Một thứ khác mà tôi thấy bị thiếu với knockout.js là đồng bộ hóa một mô hình đơn (không phải dạng xem) trên các khung nhìn khác nhau. Tôi không nghĩ rằng có một viewmodel khổng lồ mà mọi view đều chia sẻ, vì vậy tôi nghĩ rằng mỗi view sẽ có viewmodel riêng nhưng mỗi viewmodel sẽ đồng bộ với các trường chỉ là một vài mô hình ứng dụng cần thiết cho mỗi lượt xem.

Trang tôi đang tìm nạp một mô hình khổng lồ (30 trường, nhiều lớp quan hệ cha/con) và tôi cho rằng tất cả các kiểu xem của tôi đều đồng bộ hóa với mô hình này. Tôi đã nghiên cứu Knockback.js (kết hợp knockout.js và backbone.js) tuy nhiên tôi đã kết thúc viết lại phần lớn các chức năng như tìm nạp, đặt, lưu, vì trang đang nhận dữ liệu từ API (và tôi có thể 't chỉ cần đồng bộ một mô hình toàn bộ qua lại với máy chủ) vì vậy tôi quyết định chống lại nó.

ví dụ trực quan của ứng dụng của tôi:

(mô hình lớp) M | M

(lớp chế độ xem/xem) VM-V | VM-V | VM-V | VM-V


một ví dụ khác

Một mô hình ví dụ sẽ là tài = {firstName: "đầu tiên", lastName: "cuối cùng", ...}

một viewmodel chỉ cần tên đầu tiên, viewmodel khác chỉ cần tên cuối cùng
ViewModelA = {firstName: app.User.firstName()}
ViewModelB = {firstName: app.User.lastName()}

Cách duy nhất để làm điều này để xác định một hệ thống pub/sub cho các thay đổi Model và Viewmodel? Đây có phải là kiến ​​trúc tốt/bền vững không? Tôi có thiếu khái niệm cơ bản ở đây không? Mọi lời khuyên đều được chào đón.

Trả lời

5

Nếu tôi đọc chính xác, có rất nhiều câu hỏi ở đây tập trung vào cách xây dựng MVVM/SPA với Knockout. Có một vài điều để giải quyết, như bạn đã chỉ ra. Một là cách giao tiếp giữa các cặp viewmodel/view.

Chế độ xem chínhModel Một cách để làm điều đó là có mô hình chế độ xem chính làm câu trả lời từ @Tyrsius. Vỏ của bạn có thể có một mô hình xem có liên kết với nhiều dữ liệu có sẵn hơn. Chế độ xem mô hình chính cũng có thể dàn xếp các mô hình xem con. Nếu bạn đi theo lộ trình này thì bạn phải cẩn thận để ràng buộc vỏ bên ngoài với khung nhìn chính và khung bên trong đến các phần tử HTML cụ thể trong DOM. Các mô hình viewmodel chủ có thể tạo thuận lợi cho việc giao tiếp giữa chúng nếu cần thiết.

Chế độ xem/ViewModel được tách riêng Một tùy chọn khác là sử dụng các cặp viewmodel/view và không có chế độ xem chính. Mỗi chế độ xem được tải vào một vùng của DOM và tự ràng buộc. Chúng hoạt động như các đơn vị riêng biệt và được tách rời khỏi nhau. Bạn có thể sử dụng pub/sub để sau đó nói chuyện giữa, nhưng nếu tất cả những gì bạn cần là một cách để dữ liệu được đồng bộ hóa thông qua các quan sát, Knockout cung cấp nhiều tùy chọn. Cái tôi thích là có mỗi đối tượng mô hình bề mặt viewmodel. Vì vậy, một khung nhìn có một viewmodel mà bề mặt dữ liệu (từ một mô hình) đó là cụ thể cho xem. Vì vậy, nhiều chế độ xem có thể hiển thị cùng một mô hình theo nhiều cách khác nhau. Vì vậy, khi một khung nhìn cập nhật một thuộc tính viewmodel (đó là trong một mô hình), nó sẽ gợn sóng đến bất kỳ khung nhìn tải nào khác cũng sử dụng cùng một mô hình.

DataContext Đi xa hơn một chút, bạn có thể tạo mô đun datacontext quản lý dữ liệu trong các mô hình. Bạn yêu cầu datacontext cho một mô hình (ví dụ: danh sách các khách hàng) và datacontext kiểm tra nếu nó có chúng đã được cahced chưa và nếu không, nó đi và nhận chúng từ một cuộc gọi ajax. Dù bằng cách nào được trừu tượng hóa từ mô hình và mô hình xem. Datacontext lấy dữ liệu và trả về một mô hình (s) cho viewmodel. Bằng cách này bạn đang rất tách rời, nhưng bạn có thể chia sẻ dữ liệu (mô hình của bạn) thông qua datacontext.

Tôi có thể tiếp tục ... nhưng hãy cho tôi biết nếu điều này đang trả lời câu hỏi của bạn. Nếu không, vui lòng trả lời bất kỳ chi tiết cụ thể nào khác.

** Disclaimer: Tôi đang xây dựng một khóa học Pluralsight trên SPA của (sử dụng Knockout và chiến lược này) :-)

+0

+1 để đề cập đến pub/sub, tôi quên đề cập đến điều đó. – Tyrsius

+0

Trước hết, xin lỗi vì câu trả lời chậm trễ John và @Tysirius, tôi đã đưa vào một dự án khác trong tuần qua. Tôi thực sự thích cấu trúc V/VM được tách riêng mà bạn đang đề xuất. Tôi thích ý tưởng của một mô hình tổng thể bền bỉ bất kể những gì "trang" bạn đang ở trong SPA. Về cơ bản, tôi giải thích rằng tôi có một mô hình có 10 trường (ngay bây giờ là ko.observable()), sau đó nhiều Mô hình Xem đồng bộ với một phần đại diện của mô hình đó (chỉ một vài trường), và "gợn sóng" đang làm việc rực rỡ. –

+0

Vui mừng khi biết nó hoạt động cho bạn. Đó là một mẫu IMO rắn. –

2

Đây là một lĩnh vực phổ biến đáng chú ý ngay bây giờ, vì vậy tôi hy vọng bạn sẽ nhận được một số câu trả lời tốt hơn, nhưng ở đây đi.

Model

Vâng, bạn hoàn toàn nên có một đại diện phía máy chủ của dữ liệu, đó là mô hình của bạn. Điều này phụ thuộc vào máy chủ của bạn và cơ sở dữ liệu của bạn. Đối với MVC3, đây là mô hình thực thể của bạn. Đối với Django hoặc Ruby, bạn sẽ có các mô hình db được xác định là một phần của thiết lập db của bạn. Phần này phụ thuộc vào công nghệ cụ thể của bạn. Tuy nhiên, theo số điện thoại bạn nên có mô hình và máy chủ cần hoàn toàn thực hiện xác thực dữ liệu.

Các ứng dụng (ViewModel)

Đó là khuyến cáo rằng quan điểm của bạn đều có viewmodel riêng của họ.Sau đó, trang của bạn có thể có chế độ xem, một Chế độ xem ứng dụng nếu bạn sẽ theo dõi tất cả chúng. Nếu bạn đi tuyến đường này, chế độ xem ứng dụng phải chịu trách nhiệm chuyển đổi giữa các chế độ xem và triển khai bất kỳ logic cấp ứng dụng nào khác (như điều hướng băm băm, một công cụ trang đơn phổ biến khác). Hệ thống phân cấp này rất quan trọng, nhưng không phải lúc nào cũng đơn giản. Nó sẽ đi xuống các yêu cầu cụ thể của ứng dụng của bạn. Bạn không bị giới hạn ở chế độ xem màn hình phẳng. Đây không phải là phương pháp duy nhất có thể.

Ad Hoc Ví dụ:

​var ThingViewModel = function(name, data){ 
    this.name = ko.observable(name); 
    //Additional viewmodel stuffs 
}; 

var AppViewModel = function(initialData){ 
    //Process initial data  
    this.thing = new ThingViewModel(someName, someData); 

}; 

Tôi đang làm việc trên một dự án tương tự ngay bây giờ, hoàn toàn cho việc học tập (không phải là một ứng dụng thế giới thực), được lưu trữ here on GitHub, nếu bạn muốn có một cái nhìn tại một số ngoại lệ thực sự. Lưu ý, chi nhánh dev là khá một chút trước chi nhánh master vào lúc này. Tôi chắc chắn nó có chứa một số mẫu xấu (cảm thấy tự do để chỉ ra chúng, tôi cũng học), nhưng bạn có thể học được một vài điều từ nó.

+0

Xin chào! - Lại: quan điểm của bạn về "bạn hoàn toàn nên có một đại diện phía máy chủ của dữ liệu", điều này có nghĩa là mỗi thay đổi để viewmodel của bạn nên đi qua máy chủ đầu tiên? – MikeW

+0

Tuyệt đối không! Những gì tôi có nghĩa là một lớp mô hình nên tồn tại trên máy chủ, bởi vì máy chủ là sự bền bỉ dữ liệu này (thường là một cơ sở dữ liệu), và máy chủ phải làm việc với nó. Các hoạt động viewmodel Knockout sẽ vẫn còn trên máy khách * càng nhiều càng tốt *. – Tyrsius

1

tôi có một giải pháp phức tạp tương tự trong đó tôi đang làm lại một ứng dụng WPF vào một phiên bản web. Phiên bản WPF xử lý các đối tượng miền phức tạp mà nó liên kết với các khung nhìn theo các mô hình trình diễn.

Trong phiên bản web, tôi đã triển khai các mô hình chế độ xem phía máy chủ được đơn giản hóa và phần nào được dịch chuyển qua lại từ/sang các đối tượng miền bằng Automapper. Sau đó, các mô hình xem phía máy chủ được gửi qua lại cho máy khách dưới dạng JSON và ánh xạ vào/vào các mô hình xem Knockout tương ứng (các hàm có khả năng khởi tạo mà mỗi người chịu trách nhiệm tạo các con của họ với các tùy chọn ánh xạ) sử dụng plugin ánh xạ.

Khi tôi cần lưu/xác thực giao diện người dùng, tôi ánh xạ tất cả hoặc một phần mô hình xem Knockout của mình trở lại đối tượng Javascript đơn giản, đăng nó dưới dạng JSON, khung MVC liên kết lại với mô hình chế độ xem phía máy chủ được Automapped trở lại đối tượng miền, được xác nhận và có thể được cập nhật bởi lớp miền của chúng tôi, và sau đó một biểu đồ đầy đủ hoặc một phần đã sửa đổi được trả lại và được ánh xạ lại.

Hiện tại tôi chỉ có một trang chính nơi hành động Knockout diễn ra nhưng tôi dự đoán rằng bạn sẽ kết thúc với nhiều bối cảnh cần xử lý cùng một mô hình (đối tượng miền của tôi) tùy thuộc vào những gì tôi đang làm với họ.

Tôi đã cấu trúc thư mục mô hình chế độ xem phía máy chủ, v.v. với dự đoán về điều này, cũng như cấu trúc của các kiểu xem Knockout của tôi. Cho đến nay phương pháp này hoạt động rất tốt. Hi vọng điêu nay co ich.

+0

cảm ơn cho câu trả lời này, tôi chưa bắt đầu lập bản đồ JSON nhưng tôi chắc chắn điều này sẽ có ích! –

0

Trong một dự án tôi đã phát triển một khung công tác (sử dụng KnockoutJS) cung cấp các cặp View/ViewModel được tách riêng và cho phép tạo nhanh các bản xem trước trong một chế độ xem. Việc xử lý toàn bộ khung nhìn và khung nhìn con được cung cấp bởi khung công tác. Nó hoạt động như MVVM với XAML trong WPF.

Hãy xem http://visto.codeplex.com