KnockoutJS:通过点击绑定创建一个可观察对象

KnockoutJS: Create an observable from click binding

本文关键字:一个 对象 观察 创建 绑定 KnockoutJS      更新时间:2023-09-26

我可能想太多了,但我想做的是创建一个observableArray从点击事件绑定到一个函数。基本上,当我点击一个按钮时,我需要根据event.target.html()过滤结果,并创建一个可观察对象,以便在页面后面的foreach循环中使用。

首先我有一个按钮。

<button data-bind="click: getData">Button Text</button> 

基于Button Text筛选结果的函数

self.filterFunction = function(x) {
      // do things here
      return (obj);
}

Click与getData函数绑定,该函数使用Click中的DOM元素调用filterFunction并创建一个可观察数组

self.getData = function(item, event) {
      viewModel.myFilteredData = ko.observableArray(self.filterFunction($(event.target).html()));  
}

然后我循环myFilteredData,但失败了。

<!-- ko foreach: myFilteredData -->
       // Generate HTML here
<!-- /ko -->

我的直觉告诉我,我在逻辑上失败了,有一个更有效的方法来做这件事。我还想找出一种方法,有myFilteredData基于一些预先设置的Button Text预填充,所以HTML可以在初始页面加载,点击任何按钮之前生成。

谢谢。

也许你的问题是你的foreach绑定绑定到一个不同的可观察数组,而不是你在点击后生成的。这样想吧。给定这个视图模型:

{
    myFilteredData: ko.observableArray()
}

…当ko.applyBindings发生时,Knockout订阅此ko.observableArray进行更新,并循环遍历(现在为空)数组。

现在,点击处理程序发生了:
viewModel.myFilteredData = ko.observableArray(self.filterFunction($(event.target).html()));  

上面建立的订阅没有被触发,因为可观察数组没有改变;相反,你用另一个代替了它。不幸的是,Knockout不知道这个新版本。

我建议不要用新数组替换数组,而是用新数据填充现有数组:

viewModel.myFilteredData(self.filterFunction($(event.target).html()));  

为什么不直接在视图模型中设置一个observableArray,创建一个绑定到button click的函数,然后传入每个对象呢?用a for each将按钮绑定到一些可观察对象或实体,然后在按钮上单击一个参数,将其推入observableArray

Solefald,肯定有更好的方法。

首先,向视图模型添加一个自己的"过滤器"对象数组,以及一个ko.computed来提供过滤后的数据。将过滤器按钮绑定到"filter"对象数组。像这样:

var viewModel = function(){
    var self = this;
    self.filters = [
        {buttonText:'Button Text', filterKey:'filterKeyOne'},
        {buttonText:'Other Button Text', filterKey:'filterKeyTwo'}
    ];
    self.selectedFilterKey = ko.observable('none');
    self.setFilter = function(){...}
    self.data = ko.observableArray([...]);
    self.filteredData = ko.computed(function(){...});
}

和这样绑定:

<div data-bind="foreach: filters">
    <button data-bind="click : $parent.setFilter, text: buttonText"></button>
</div>
<div data-bind="foreach: filteredData">
    ...
</div>

通过让Knockout为过滤器按钮绑定单击,您将获得整个过滤器对象作为"runFilter"函数中的第一个参数。然后你可以像这样实现你的过滤器按钮点击处理程序(在这个例子中是"setFilter"):

self.setFilter = function(filterItem){
   self.selectedFilterKey(filterItem.filterKey);
};

通过使"selectedFilterKey"成为一个可观察对象,你可以将你的filteredData实现为ko.computed,它会在"selectedFilterKey"发生变化时自动更新ui,如下所示:

...
self.filteredData = ko.computed(function(){
    //pick the right filter function
    var filterFunction = filterOne;//assign the default filter function
    switch(self.selectedFilterKey()){
        case 'filterKeyOne':
            filterFunction = self.filterOne;//your first filter
        break;
        case 'filterKeyTwo':
            filterFunction = self.filterTwo;//your second filter
        break;
    }
    return ko.utils.arrayFilter(self.data(), function(item){        
        //return true if item passes filter
        return filterFunction(item);
    });
});
...

功能方法

如果你想使用更函数式的编程方法,试着在过滤器对象中定义你的过滤器函数。

self.filters = [
    {buttonText:'Button Text', filterFunction:function(item){...}},
    {buttonText:'Other Button Text', filterFunction:function(item){...}}
];

并存储所选函数,而不是键

self.setFilter = function(filterItem){
   self.selectedFilterFunction(filterItem.filterFunction);
};

和跳过switch语句

...
self.filteredData = ko.computed(function(){
    return ko.utils.arrayFilter(self.data(), function(item){        
        //return true if item passes filter
        return self.selectedFilterFunction()(item);
    });
});
...

如果你想了解更多关于这种排序方法的信息,你可以在我的博客上阅读:http://ryanrahlf.com/sorting-tables-by-column-header-with-knockout-js/

我希望这对你有帮助!