2012-07-02 27 views
37

Tôi muốn biết cách tạo mảng quan sát được tính toán.Cách tạo mảng quan sát được tính trong Knockout

Trong mô hình khung nhìn của mình, tôi có 2 mảng quan sát được, và tôi muốn có một mảng có thể quan sát được tính toán đơn giản là cả hai mảng được kết hợp.

function ViewModel() { 
    var self = this; 
    self.listA= ko.observableArray([]); 
    self.listB = ko.observableArray([]); 
    self.masterList= //combine both list A and B 

Trả lời

33

Điều này sẽ kết hợp hai mảng và trả về danh sách kết hợp. Tuy nhiên, nó không phải là một mảng có thể quan sát được tính toán (không biết nếu đó là thậm chí có thể), nhưng một tính toán thường xuyên quan sát được.

self.masterList = ko.computed(function() { 
    return this.listA().concat(this.listB()); 
}, this); 
+18

Tôi tin câu trả lời này là thiếu sót cho hầu hết các trường hợp sử dụng: giá trị của quan sát được tính toán là một mảng thông thường, không phải là một mảng quan sát được (gần như được nêu trong câu trả lời). Do đó, việc cập nhật 'listA' hoặc' listB' sẽ thay thế hoàn toàn bản thân mảng thay vì cập nhật nội dung của nó (đó là những gì chúng ta muốn trong 99% các trường hợp). ** Điều này có nghĩa là bạn không nên liên kết các khung nhìn với điều này. ** Trong thực tế, mã này hữu ích như biến thể không được tính toán của nó. Xem các câu trả lời khác cho các cách tiếp cận khác nhau. – tne

+0

Nó sẽ không hoạt động trong trường hợp này, nhưng plugin knockout [knockout-projections] (https://github.com/stevesanderson/knockout-projections) thực hiện các mảng quan sát được tính toán hiệu quả hơn bằng cách sử dụng [đăng ký thay đổi mảng mới] http://blog.stevensanderson.com/2013/10/08/knockout-3-0-release-candidate-available/). Plugin này có thể được mở rộng để hỗ trợ hoạt động concat hiệu quả. – Singularity

7

Một ObservableArray chỉ là một quan sát với một vài thuộc tính khác. Do đó, một quan sát được tính toán trả về một mảng trong phần đóng sẽ được coi là một mảng.

+3

Vâng, sắp xếp. Tôi chỉ thử nghiệm nó và có vẻ như là trừ khi nó được khai báo là một mảng quan sát được, các phương thức như shift và pop không bị phá vỡ cho bạn. – Eirinn

9

Tôi biết đây là một câu hỏi cũ nhưng tôi nghĩ rằng tôi muốn ném trả lời của tôi trong đó:

var u = ko.utils.unwrapObservable; 

ko.observableArray.fn.filter = function (predicate) { 
    var target = this; 

    var computed = ko.computed(function() { 
     return ko.utils.arrayFilter(target(), predicate); 
    }); 

    var observableArray = new ko.observableArray(u(computed)); 

    computed.subscribe(function (newValue) { observableArray(newValue); }); 

    return observableArray; 
}; 
10
self.masterList = ko.observableArray(); 
ko.computed(function() { 
    self.masterList(self.listA().concat(self.listB())); 
}); 

Tương tự như câu trả lời Joe Flateau trong tinh thần, nhưng tôi thích nghĩ phương pháp này là đơn giản hơn .

+0

Đây là cách tôi sẽ làm điều đó là tốt, nhưng điều này vẫn không bị vấn đề như câu trả lời được chấp nhận; trong bất kỳ thay đổi nào sẽ khiến cho bất kỳ khung nhìn nào bị ràng buộc với 'masterList' được vẽ lại hoàn toàn? –

+0

@AdamLewis: Vâng, điều này thực sự xây dựng lại toàn bộ mảng và tùy thuộc vào công cụ xem mà có thể hoặc không thể hiển thị lại toàn bộ đồ thị DOM cho bất kỳ chế độ xem nào bị ràng buộc với nó (không nhất thiết là có thể tạo ra sự khác biệt và áp dụng nó). Lưu ý rằng nó vẫn có thể là giải pháp tốt nhất để tránh nhiều cập nhật. Tuy nhiên, đây không phải là vấn đề tôi đề cập đến câu trả lời mà bạn đề cập đến, nếu công cụ xem ghi lại thuộc tính mảng (ngược lại với đường dẫn đến nó) thì nó sẽ không bao giờ phát hiện ra rằng bạn hoán đổi mảng (vì nó không thể quan sát được) và do đó sẽ không bao giờ cập nhật * *. – tne

+0

@tne Tôi đang sử dụng câu trả lời này cho bây giờ, nhưng có vẻ như rất chậm ... có lẽ tôi đang làm điều gì đó sai trái. Tuy nhiên, giải pháp này có phá vỡ mục đích dự định của KO không?Có cách nào khác để giải quyết vấn đề cần một mảng quan sát được tính toán không? chỉ cần tự hỏi nếu đây là công cụ thích hợp để sử dụng trong trường hợp của tôi (hoặc bất kỳ). – Nate

2

Tôi không chắc đây có phải là lựa chọn hiệu quả nhất hay không - nhưng nó khá đơn giản và phù hợp với tôi. Lợi nhuận ko.computed một mảng quan sát được như sau:

self.computedArrayValue = ko.computed(function() { 
    var all = ko.observableArray([]); 
    .... 
    return all(); 
}); 

Một ví dụ làm việc của mã: Html:

<div data-bind="foreach: days"> 
    <button class="btn btn-default btn-lg day" data-bind="text: $data, click: $root.dayPressed"></button>   
</div> 

chức năng Javascript trên mô hình điểm:

self.days = ko.computed(function() { 
    var all = ko.observableArray([]); 
    var month = self.selectedMonth(); //observable 
    var year = self.selectedYear();  //observable 
    for (var i = 1; i < 29; i++) { 
     all.push(i); 
    } 
    if (month == "Feb" && year % 4 == 0) { 
     all.push(29); 
    } else if (["Jan","Mar","May","Jul","Aug","Oct","Dec"].find((p) => p == month)) { 
     [29,30,31].forEach((i) => all.push(i)); 
    } else if (month != "Feb") { 
     [29,30].forEach((i) => all.push(i));     
    } 
    return all(); 
}); 
Các vấn đề liên quan