Javascript 我如何确定是什么触发了一个计算的可观测的变化?淘汰赛 问题概述

Javascript 我如何确定是什么触发了一个计算的可观测的变化?淘汰赛 问题概述,javascript,knockout.js,Javascript,Knockout.js,我很难确定是什么触发了计算的可观测变化 我有一个下拉选择框,用于过滤表中显示的可观察数组。以下是选择框中的选项: 以下是我如何定义选择: // Javascript let filters = ["All", "Pending", "Accepted", "Rejected", "Expired"]; // HTML <select data-bind="options: filters, value: filter"> </select> 如您所见,引号数组中的

我很难确定是什么触发了计算的可观测变化

我有一个下拉选择框,用于过滤表中显示的可观察数组。以下是选择框中的选项:

以下是我如何定义选择:

// Javascript
let filters = ["All", "Pending", "Accepted", "Rejected", "Expired"];

// HTML
<select data-bind="options: filters, value: filter"> 
</select>
如您所见,引号数组中的status属性与下拉列表中的过滤器值进行比较。一切都很好。但现在我也在数组中添加关键字搜索(如下图所示):

我将关键字文本字段绑定到可观察的:

self.keyword = ko.observable();
修改代码以处理关键字搜索 我相信通过更改以下内容,我可以轻松修改计算的可观察代码以处理关键字搜索:

return i.status() == filter;
类似于此(与数组中的其他属性相比)

但是

我不知道如何确定是通过过滤器下拉列表过滤数组,还是通过关键字过滤数组。不知何故,我需要知道是什么触发了计算的可观测变化,不是吗

有什么想法吗

以下是完整的视图模型:

// Quotes View Model

// +---------------------------------------------------------------------------+
// |  Quote View Model                                                         |
// |                                                                           |
// |  quotes-view-model.js                                                     |
// +---------------------------------------------------------------------------+
// |  Shows a list of all Quotes                                               |
// +---------------------------------------------------------------------------+/

let QuoteModel = function(id, quote_number, created_date, expiration_date, amount, client, status){

     this.id = ko.observable();
     this.quote_number = ko.observable(quote_number);
     this.created_date = ko.observable(created_date);
     this.expiration_date = ko.observable(expiration_date);
     this.amount = ko.observable(amount);
     this.client = ko.observable(client);
     this.status = ko.observable(status);

}



let ClientModel = function(id, fullName){
    this.id = ko.observable(id);
    this.fullName = ko.observable(fullName);
}

// Define Status Dropdown filters
let filters = ["All", "Pending", "Accepted", "Rejected", "Expired"];


function QuoteViewModel() {

    var self = this; // Scope Trick


    /* QUOTE Observables */
    self.quotes = ko.observableArray();
    self.clients = ko.observableArray();

    self.keyword = ko.observable();
    self.searchType = ko.observable();

    self.filters = ko.observableArray(filters);
    self.filter = ko.observable('');

    self.filteredItems = ko.computed(function() {
        var filter = self.filter();
        if (!filter || filter == "All") {
            return self.quotes();
        } else {
            return ko.utils.arrayFilter(self.quotes(), function(i) {
                console.log(i);
                return i.status() == filter;
            });
        }
    });

    /* GET PAGE DATA */

    /* CLIENTS */
           $.getJSON(apiCustomersAll,
            function(data) {
                var fullName;
                $.each(data,
                    function(key, val) {
                        fullName = val.first_name + " " + val.last_name;
                        self.clients.push(new ClientModel(val.id, fullName));
                    });
            });

          $.getJSON(apiQuotesAll,
            function(data) {
                var fullName;
                $.each(data,
                    function(key, val) {
                        fullName = self.getClientById(val.client_id);
                        console.log(`Full name is ${fullName}`);
                        self.quotes.push(new QuoteModel(val.id, 
                                                        val.quote_number, 
                                                        formatDate(val.created_date), 
                                                        formatDate(val.expiration_date), 
                                                        val.amount, 
                                                        fullName, 
                                                        val.status
                                                      ));
                    });
            });


        // Search Client Array, Return Full Name
        self.getClientById = function(id) {
            const client = self.clients().find(function(val){
                return val.id() == id;
            });

            if(client) {
                return client.fullName();   
            }

            return undefined;
            }



       self.search = function(){
         // to do
       }


}



ko.applyBindings(new QuoteViewModel());

仅使用一个文本框来允许自由文本搜索将给过滤器增加一些复杂性,我可以理解为什么您添加了
searchType
observable。但是,您可以测试键入的文本是否可以被视为数量,然后使用此检查区分过滤器。我相信,当您检查数量是否大于插入值时,过滤器会更有用,而不是检查是否完全相等,具体取决于您

此外:由于这些过滤器的组合将应用于两个实体(引号和客户机),因此自由文本过滤器应作为两个数据集之间的交集或并集应用,也取决于您。在我下面的建议中,我再次过滤生成的数据集(交叉点):

var quoteStatusOptions=[“全部”、“待定”、“接受”、“拒绝”、“过期”];
风险值数据={
引号:[{id:1,客户机:1,金额:300,状态:“待定”},{id:2,客户机:3,金额:200,状态:“已接受”},{id:3,客户机:2,金额:100,状态:“已过期”},
客户:[{id:1,全名:“Leanne Graham”},{id:2,全名:“Ervin Howell”},{id:3,全名:“Clementine Bauch”}]
};
函数QuoteModel(数据){
this.id=ko.可观察(data.id);
this.client=ko.observable(data.client);
本金额=可观察到的ko(数据金额);
this.status=ko.可观察(data.status);
}
函数ClientModel(数据){
this.id=ko.可观察(data.id);
this.fullName=ko.observable(data.fullName);
}
函数QuoteViewModel(数据){
var self=这个;
self.quotes=ko.observearray(ko.utils.arrayMap(data.quotes,function)(quote){
返回新的QuoteModel(quote);
}));
self.quoteStatusOptions=ko.observearray(quoteStatusOptions);
self.quoteStatusFilter=ko.可观察(“”);
self.clients=ko.observearray(ko.utils.arrayMap(data.clients,function(client)){
返回新的ClientModel(客户端);
}));
self.searchTextFilter=ko.可观察(“”);
self.filteredQuotes=ko.computed(函数(){
var quotes=self.quotes();/*跟踪引号数组更改*/
var quoteStatusFilter=self.quoteStatusFilter();/*跟踪报价状态筛选器更改*/
var clients=self.clients();/*跟踪客户端数组更改*/
var searchTextFilter=self.searchTextFilter();/*跟踪文本筛选器更改*/
var isAmount=!isNaN(parseFloat(searchTextFilter))&&isFinite(searchTextFilter);
var filteredQuotes=ko.utils.arrayFilter(引号,函数(引号){
var includeAll=!QUOTESTATUSPILTER | QUOTESTATUSPILTER==“全部”;
var includeByStatus=includeAll | | quote.status.peek()==quoteStatusFilter;
var includebamount=parseFloat(quote.amount.peek())>=parseFloat(searchTextFilter);
返回isAmount?includeByStatus&&includeByAmount:includeByStatus;
});
var filteredClients=ko.utils.arrayFilter(客户端,函数(客户端){
var includeal=searchTextFilter==“”;
var includeByName=~client.fullName.peek().toLowerCase().indexOf(searchTextFilter.toLowerCase());
return isAmount?true:includeAll | | includeByName;
});
var结果=[];

对于(var i=0,l=filteredQuotes.length;我“不知何故,我需要知道是什么触发了计算的可观测值的改变,不是吗?”事实上,你没有,因为从用户体验的角度来看,一旦任何一个条件发生变化,用户都会希望你根据这两个条件过滤数组,而不管哪一个条件发生了变化。哦,等等,我想我明白了……你是说我应该保持原样,只需将关键字过滤逻辑与状态一起添加吗?如果是,w我需要使用&&和| |吗?你能给我一个例子,说明我如何将逻辑添加到当前函数中来处理关键字吗?你已经自己选择了它,所以这很好。你所需要做的就是将你的
状态
比较与
关键字
比较组合成一个布尔表达式(也就是说,在它们之间使用
&&
,同时将您的
|
放在每个代码中)。
return i.fullName() == keyword || i.amount() == keyword || ..etc
// Quotes View Model

// +---------------------------------------------------------------------------+
// |  Quote View Model                                                         |
// |                                                                           |
// |  quotes-view-model.js                                                     |
// +---------------------------------------------------------------------------+
// |  Shows a list of all Quotes                                               |
// +---------------------------------------------------------------------------+/

let QuoteModel = function(id, quote_number, created_date, expiration_date, amount, client, status){

     this.id = ko.observable();
     this.quote_number = ko.observable(quote_number);
     this.created_date = ko.observable(created_date);
     this.expiration_date = ko.observable(expiration_date);
     this.amount = ko.observable(amount);
     this.client = ko.observable(client);
     this.status = ko.observable(status);

}



let ClientModel = function(id, fullName){
    this.id = ko.observable(id);
    this.fullName = ko.observable(fullName);
}

// Define Status Dropdown filters
let filters = ["All", "Pending", "Accepted", "Rejected", "Expired"];


function QuoteViewModel() {

    var self = this; // Scope Trick


    /* QUOTE Observables */
    self.quotes = ko.observableArray();
    self.clients = ko.observableArray();

    self.keyword = ko.observable();
    self.searchType = ko.observable();

    self.filters = ko.observableArray(filters);
    self.filter = ko.observable('');

    self.filteredItems = ko.computed(function() {
        var filter = self.filter();
        if (!filter || filter == "All") {
            return self.quotes();
        } else {
            return ko.utils.arrayFilter(self.quotes(), function(i) {
                console.log(i);
                return i.status() == filter;
            });
        }
    });

    /* GET PAGE DATA */

    /* CLIENTS */
           $.getJSON(apiCustomersAll,
            function(data) {
                var fullName;
                $.each(data,
                    function(key, val) {
                        fullName = val.first_name + " " + val.last_name;
                        self.clients.push(new ClientModel(val.id, fullName));
                    });
            });

          $.getJSON(apiQuotesAll,
            function(data) {
                var fullName;
                $.each(data,
                    function(key, val) {
                        fullName = self.getClientById(val.client_id);
                        console.log(`Full name is ${fullName}`);
                        self.quotes.push(new QuoteModel(val.id, 
                                                        val.quote_number, 
                                                        formatDate(val.created_date), 
                                                        formatDate(val.expiration_date), 
                                                        val.amount, 
                                                        fullName, 
                                                        val.status
                                                      ));
                    });
            });


        // Search Client Array, Return Full Name
        self.getClientById = function(id) {
            const client = self.clients().find(function(val){
                return val.id() == id;
            });

            if(client) {
                return client.fullName();   
            }

            return undefined;
            }



       self.search = function(){
         // to do
       }


}



ko.applyBindings(new QuoteViewModel());