KnockOutJS - Nhiều ViewModels trong một View


201

Tôi nghĩ rằng ứng dụng của tôi hiện đang trở nên khá lớn, quá lớn để xử lý mỗi View với một ViewModel duy nhất.

Vì vậy, tôi tự hỏi sẽ khó khăn thế nào khi tạo nhiều ViewModels và tải tất cả chúng vào một View. Với một lưu ý rằng tôi cũng cần có khả năng truyền dữ liệu X ViewModel vào dữ liệu Y ViewModel để các ViewModel riêng lẻ cần có khả năng giao tiếp với nhau hoặc ít nhất là nhận thức được nhau.

Chẳng hạn, tôi có một trình đơn <select>thả xuống, phần thả xuống được chọn đó có trạng thái được chọn cho phép tôi chuyển ID của mục đã chọn trong <select>một lệnh gọi Ajax khác trong một ViewModel riêng biệt ....

Bất kỳ điểm nào về việc xử lý nhiều ViewModels trong một View đều được đánh giá cao :)


12
Đối với những người đến câu hỏi này, xin vui lòng cuộn qua câu trả lời được chấp nhận. Knockout hiện hỗ trợ nhiều bối cảnh ràng buộc . Không cần một người khổng lồ masterVM.
Carrie Kendall

Câu trả lời:


150

Nếu tất cả chúng cần phải nằm trên cùng một trang, một cách dễ dàng để làm điều này là có một mô hình khung nhìn chính chứa một mảng (hoặc danh sách thuộc tính) của các mô hình khung nhìn khác.

masterVM = {
    vmA : new VmA(),
    vmB : new VmB(),
    vmC : new VmC(),
}

Sau đó, bạn masterVMcó thể có các thuộc tính khác nếu cần, cho chính trang đó. Giao tiếp giữa các mô hình khung nhìn sẽ không khó khăn trong tình huống này vì bạn có thể chuyển tiếp qua masterVMhoặc bạn có thể sử dụng $parent/ $roottrong các ràng buộc hoặc một số tùy chọn tùy chỉnh khác.


2
Vì vậy, tôi có thể làm một cái gì đó như: data-bind = "text: masterVM.vmA", tôi cho rằng tôi vẫn có thể sử dụng ko.applyBindings với phần tử DOM được đính kèm. Giả sử điều đó cũng có nghĩa là tôi có thể làm: data-bind = "$ Parent.masterVm"?
CLiown

12
@CLiown Bạn có thể sử dụng with:liên kết, vì vậy Bạn sẽ không lặp lại chính mình
AlfeG

4
@CLiown Có, bạn có thể làm điều đó nếu bạn bị ràng buộc với masterVM. Bạn cũng có thể sử dụng liên kết "với" để giúp tránh cú pháp dấu chấm khi bạn đi sâu vào các mô hình chế độ xem phụ.
John Papa

1
Tôi nghĩ rằng cách tiếp cận này rất hạn chế ... Bây giờ trong trường hợp của tôi, tôi đang sử dụng ASP.Net MVC4, điều này không có ích vì sẽ có các chế độ xem một phần có ViewModels riêng và các phần / Nội dung, không nên can thiệp lẫn nhau và do kết xuất có điều kiện Sẽ rất khó sử dụng phương pháp này.
bhuvin

1
@bhuvin bằng cách sử dụng <! - ko stopBinding: true -> sẽ giúp bạn với nhiều mô hình chế độ xem và các phần xem một phần. Xem knockmeout.net/2012/05/quick-tip-skip-binding.html để biết thêm thông tin.
Micaël Félix

285

Knockout hiện hỗ trợ nhiều ràng buộc mô hình. Các ko.applyBindings()phương pháp lấy một tham số tùy chọn - yếu tố và hậu duệ của nó mà các ràng buộc sẽ được kích hoạt.

Ví dụ:

ko.applyBindings(myViewModel, document.getElementById('someElementId'))

Điều này hạn chế kích hoạt thành phần có ID someElementIdvà con cháu của nó.

Xem tài liệu để biết thêm chi tiết.


72
Nếu bạn muốn sử dụng bộ chọn jQuery, bạn sẽ muốn thêm [0]để chỉ định một phần tử DOM thực tế (thay vì đối tượng jQuery) như sau:ko.applyBindings(myViewModel, $('#someElementId')[0])
MrBoJangles

3
Đây phải là câu trả lời được chấp nhận. Bạn vẫn có thể sử dụng một đối tượng chính như câu trả lời hiện được chấp nhận và sau đó liên kết các chế độ xem riêng lẻ với các thành phần thích hợp của chúng trên trang. Điều này sẽ tiết kiệm hiệu suất và giới hạn phạm vi cần thiết cho liên kết dữ liệu.
Kevin Heidt

Có thể giao tiếp viewModels với nhau bằng cách tiếp cận này không? tức là tôi có TaskVM và NoteVM. Nhiệm vụ có thể có Ghi chú. Do đó, TaskVM của tôi phải có một có thể quan sát được, cụ thể là các ghi chú có loại là TaskVM. Bạn có thể chia sẻ một ví dụ cho một trường hợp như vậy?
ahmet

Có lẽ tốt nhất để hỏi về giao tiếp giữa các VM trong một câu hỏi mới.
Richard Nalezynski

21

Đây là câu trả lời của tôi sau khi hoàn thành dự án rất lớn với rất nhiều ViewModels trong chế độ xem đơn.

Xem Html

    <!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
</head>
<body>
    <div id="container1">
        <ul>
            <li >Container1 item</li>
            <!-- ko foreach: myItems -->
            <li>Item <span data-bind="text: $data"></span></li>
            <!-- /ko -->
        </ul>
    </div>

    <div id="container2">
        <ul>
            <li >Container2 item</li>
            <!-- ko foreach: myItems -->
                <li>Item <span data-bind="text: $data"></span></li>
            <!-- /ko -->
        </ul>
    </div>

    <script src="js/jquery-1.11.1.js"></script>
    <script src="js/knockout-3.0.0.js"></script>
    <script src="js/DataFunction.js"></script>
    <script src="js/Container1ViewModel.js"></script>
    <script src="js/Container2ViewModel.js"></script>

</body>
</html>

Đối với chế độ xem này, tôi đang tạo 2 mô hình xem cho id = container1 và id = container2 trong hai tệp javascript riêng biệt.

Container1ViewModel.js

function Container1ViewModel()
{
    var self = this;
    self.myItems = ko.observableArray();
    self.myItems.push("ABC");
    self.myItems.push("CDE");

} 

Container2ViewModel.js

function Container2ViewModel() {
    var self = this;
    self.myItems = ko.observableArray();
    self.myItems.push("XYZ");
    self.myItems.push("PQR");

}

Sau đó, sau khi 2 chế độ xem này được đăng ký dưới dạng chế độ xem riêng biệt trong DataFunction.js

var container1VM;
var container2VM;

$(document).ready(function() {

    if ($.isEmptyObject(container1VM)) {
        container1VM = new Container1ViewModel();
        ko.applyBindings(container1VM, document.getElementById("container1"));
    }

    if ($.isEmptyObject(container2VM)) {
        container2VM = new Container2ViewModel();
        ko.applyBindings(container2VM, document.getElementById("container2"));
    }
});

Như thế này, bạn có thể thêm bất kỳ số lượng viewmodels nào cho các div riêng biệt. Nhưng đảm bảo không tạo mô hình xem riêng cho div bên trong div đã đăng ký.


Có thể thực hiện loại viewmodel bên trong khác thay vì là các thành phần riêng biệt của DOM không?
UserEsp

4

Kiểm tra plugin MultiModels cho Knockout JS - https://github.com/sergun/Knockout-MultiModels


6
Điều này có lợi thế gì so với ko.applyBindings (viewModel, document.getEuityById ("divName"))? Không phải nó chỉ là cú pháp đường sao?
Paolo del Mundo

1
@Paolo del Mundo Nó cũng thêm một phụ thuộc vào plugin LiveQuery.
Lars Gyrup Brink Nielsen

@PaolodelMundo mục đích của plugin là để có thể sử dụng bộ chế độ xem theo cách thức hoạt động
Serge Zwezdin

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.