2

私は、JavaScript アプリをよりスケーラブルにすることに取り組んできました。このアプリは、knockout.js を使用して、ユーザーが編集および更新できるように、ある種のデータベース アイテムのグリッドをバインドします。私は今、継承を扱い、それを継承する BaseModel とモデルを持つ道を進んでいます。私が抱えている問題は、継承するクラスによって BaseModel で定義されている計算されたオブザーバブルをオーバーライドしたいときに発生します。ユースケースはこちら。

ベース グリッドには、UI がバインドする計算されたオブザーバブルがあります。計算されたオブザーバブルは、ユーザーが入力して検索できるテキスト ボックス フィルターを使用して、オブザーバブル配列から機能します。かなり基本的です。

子クラスであるロールは、特定のタイプのグリッドであり、ビジネス要件の一部は部門用のフィルターを持つことでした。これは UI のドロップダウンです。基本クラスの計算されたオブザーバブルを、子クラスのロール実装でオーバーライドしたいと考えています。それを達成する方法がわからない。

ここに JSFiddle があります: http://jsfiddle.net/Icestorm0141/vx6843pt/6/

BaseGridViewModel:

var BaseGridViewModel = function (serverData) {
    var self = this;    

    //searchTerm is a text box that the user types to search
    self.searchTerm = ko.observable();

    //items are the data from the server
    self.items = ko.mapping.fromJS(serverData, mapping);

    //filteredItems are the filtered list of items that the grid is actually bound to
    //thus when the user searches, the UI updates automatically
    self.filteredItems = ko.computed(function () {
        if (self.searchTerm() == null || self.searchTerm() == "" || self.searchTerm().length < 3) {
            return self.items();
        } 
        else {
            return ko.utils.arrayFilter(self.items(), function (item) {
                 return item.Description().toLowerCase().indexOf(self.searchTerm().toLowerCase()) >= 0;
            });
        }
    });
}

子クラス:

var RoleGridModel = function (roleData) {
    var self = this;

    //calling the base model, I think this is the proper way to do this?
    BaseGridViewModel.call(self, roleData);

    //UI has a drop down list of departments to filter by, this is the selected filter
    self.departmentFilter = ko.observable();

    //I WANT to set the filter function for the items to something completely different
    var filterOverride = function () {
        if (self.departmentFilter() == null || self.departmentFilter() == "") {
            return self.items();
        }
        else {
            return ko.utils.arrayFilter(self.items(), function (role) {
                return role.DepartmentId() == self.departmentFilter();
            });
        }
    };
}

ここ数日、これについて多くの調査を行ってきましたが、まだ解決策を見つけていないことに驚いています。私は何か特別なことをしているような気がしませんが、誰かが何か提案をしてくれるかもしれません。私は誰に対してもオープンです!

4

4 に答える 4

2

基本クラスのフィルターを単純に破棄するのではなく、基本クラスのフィルターを継承クラスのフィルターと組み合わせることが意図されていると思います。基本クラスのフィルターを単に無視したい場合はself.filteredItems、haim770 の回答のように単純にオーバーライドできます。

それ以外の場合は、これについて多くの方法があります。1 つの方法は、次のようにすることです。

//In RoleGridModel
var baseFilteredItems = self.filteredItems; //Keep a reference to the base class's implementation
self.filteredItems = ko.computed(function () {
    var baseItems = baseFilteredItems();
    return filterByDepartment(baseItems); //filtering logic goes here
});

これは本質的にあなたが望むことを行い、計算されたものを「オーバーライド」することに最も近いものです。


計算されたものを「オーバーライド」する以外の別の方法は、任意のフィルターをサポートするように基本クラスを変更することです。何かのようなもの:

//BaseGridViewModel:

var filters = ko.observableArray([]);
self.addFilter = function(filterFunction) {
    filters.push(filterFunction);
}

self.filteredItems = ko.computed(function() {
    var items = self.items();
    filters().forEach(function (filter) {
        //filters could also be implemented to take individual items and return true or false whether that item should be filtered, but that's a side point
        items = filter(items);
    });
    return items;
});

var searchFilter = function (items) {
    var filteredItems = // filtering logic here
    return filteredItems;
};

self.addFilter(searchFilter);

//RoleGridModel
var departmentFilter = function (items) {
    var filteredItems = // filtering logic here
    return filteredItems;
}

self.addFilter(departmentFilter)

これは、継承クラスではもう少し読みやすくなりますが、基本クラスではより多くのロジックが必要になります。

于 2014-10-28T21:46:25.473 に答える
1

オーバーライドする必要がありますfilteredItems:

self.filteredItems = ko.computed(filterOverride);

フィドルを見る

于 2014-10-27T22:22:40.400 に答える
0

Retsam のソリューションが役立つと思われる他の人にとっては、addFilter を宣言するときに構文エラーがありました。修正された構文は次のとおりです。

self.addFilter = function(filterFunction) {
    filters().push(filterFunction);
}

また、フィルターは observableArray であるため、その中のアイテムは追跡されませんでした。したがって、渡した各フィルター関数は、依存しているオブザーバブルを持っていたため、元々計算されたオブザーバブルでした。例:

self.addFilter(function () {
//used to be wrapped in a computed observable
    if (self.searchTerm() == null || self.searchTerm() == "" || self.searchTerm().length < 3) {
        return self.items();
    }
    else {
        return ko.utils.arrayFilter(self.items(), function (item) {
            return item.Description().toLowerCase().indexOf(self.searchTerm().toLowerCase()) >= 0;
        });
    }
});

この例では、最初のフィルタ関数は searchTerm() に依存していますが、監視可能な配列であるフィルタ配列に追加されているため、searchTerm が更新されても UI は更新されませんでした。フィルタリング時に UI を更新する必要があるオブザーバブルごとに、サブスクリプションを介して手動で更新をトリガーする必要がありました。

self.searchTerm.subscribe(function (newValue) {
    filters.valueHasMutated();
});

これを行うためのより良い方法があるかもしれませんが、私はまだ見つけていません。

于 2014-11-18T18:50:15.837 に答える
-1

高速で信頼性の高い継承のために継承ライブラリを使用します

https://github.com/dotnetwise/Javascript-FastClass

たとえば、メソッドはプロトタイプをサポートしていません

于 2014-10-28T10:16:19.853 に答える