【问题标题】:Multiple filters in knockout.jsknockout.js 中的多个过滤器
【发布时间】:2014-04-03 11:31:45
【问题描述】:

假设我有电影数组,如果我想按类型过滤,我可以这样做

filtered = ko.computed(function() {
        var self = this;

        if ( ! self.genresFilter() || self.genresFilter() === 'all') {
            return this.sourceItems();
        } else {
            return ko.utils.arrayFilter(self.sourceItems(), function(item) {
                return app.utils.inArray(item.genre, self.genresFilter());     
            });
        }
    }, app.viewModels.games);

但是我目前遇到的问题是,如果我有类型、语言和长度的 html 下拉列表,我如何通过所有或部分过滤器有效地过滤电影,这样我就可以制作 90 分钟的俄罗斯动作片或动作片长度等?

【问题讨论】:

  • 您需要查看所有过滤器选项并应用每个具有值的过滤器。过滤器的顺序无关紧要。我们的想法是从未过滤的结果池中删除所有内容,直到只剩下适合所有过滤器的结果。

标签: javascript knockout.js filtering knockout-2.0


【解决方案1】:

您需要根据提供的每个过滤器逐步构建过滤列表。至于过滤器本身,它们应该每个都由一个可观察对象表示,或者它们全部都在一个可观察数组中。这很重要,因为它会在您更改过滤器时触发计算更新。

例子:

var filteredList = ko.computed({
    var currentList = this.sourceItems();
    var currentFilters = this.genresFilters();

    ko.utils.arrayForEach(currentFilters, function () {
        currentList = ko.utils.arrayFilter(currentList, function(filter) {
            return app.utils.inArray(filter, currentFilters);     
        });
    });

    return currentList;
});

此代码将遍历每个过滤器,获取最新过滤的列表并仅保留满足所有条件的项目。

【讨论】:

    【解决方案2】:

    我知道这是老话题,但我最近遇到了同样的问题,这是我为您的电影模型修改的解决方案。你也可以在这里查看:jsfiddle

    var MoviesModel = function(data) {
      var self = this;
      self.Genres = ko.observableArray(data.genres);
      self.Genres.unshift("All");
      self.filterGenre = ko.observable("All");
    
      self.Languages = ko.observableArray(data.languages);
      self.Languages.unshift("All");
      self.filterLanguage = ko.observable("All");
    
      self.Lengths = ko.observableArray(data.lengths);
      self.Lengths.unshift("All");
      self.filterLength = ko.observable("All");
    
      self.movies = ko.observableArray(data.movies);
    
      self.filteredMovies = ko.computed(function() {
        var filteredArray = ko.utils.arrayFilter(self.movies(), function(item) {
          return (
            (item.genre == self.filterGenre() || self.filterGenre() == "All") &&
            (item.language == self.filterLanguage() || self.filterLanguage() == "All") &&
            (item.length == self.filterLength() || self.filterLength() == "All")
          );
        });
        return filteredArray;
      });
    };
    var data = {
      genres: ["Drama", "Horror", "Sci-Fi"],
      languages: ["English", "Russian"],
      lengths: ["100", "120", "140", "160"],
      movies: [
        { name: "Godfather", genre: "Drama", language: "English", length: "160" },
        { name: "The shining", genre: "Horror", language: "English", length: "140"},
        { name: "Stalker", genre: "Sci-Fi", language: "Russian", length: "160" },
        { name: "Alien", genre: "Sci-Fi", language: "English", length: "120" },
        { name: "Russiam ark", genre: "Drama", language: "Russian", length: "100" },
        { name: "Psycho", genre: "Horror", language: "English", length: "120" }
      ]
    };
    
    var viewModel = new MoviesModel(data);
    ko.applyBindings(viewModel);
    table td {
      padding-right: 20px;
    }
    <table>
          <thead>
            <tr>
              <td>Movie name</td>
              <td>Genre</td>
              <td>Language</td>
              <td>Length</td>
            </tr>
            <tr>
              <td></td>
              <td>
                <select data-bind="options: Genres, value: filterGenre"></select>
              </td>
              <td>
                <select
                  data-bind="options: Languages, value: filterLanguage"
                ></select>
              </td>
              <td>
                <select data-bind="options: Lengths, value: filterLength"></select>
              </td>
            </tr>
          </thead>
    
          <tbody data-bind="foreach: filteredMovies">
            <tr>
              <td data-bind="text: name"></td>
              <td data-bind="text: genre"></td>
              <td data-bind="text: language "></td>
              <td data-bind="text: length"></td>
            </tr>
          </tbody>
     </table>
    
    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

    【讨论】:

      【解决方案3】:

      过滤结果是针对值的组合,可以通过迭代所有可能的过滤器来完成,应用用户选择的内容,并从结果中删除不适合过滤器的项目。应用过滤器的顺序无关紧要。这些项目必须符合所有标准才能成为有效结果,因此您可以在不符合的情况下立即丢弃它们。

      这是一些伪代码。

      # item1:
      # color: red
      # price: 5
      # language: EN
      
      # item2:
      # color: red
      # price: 10
      # language: RU
      
      # item3:
      # color: green
      # price: 7
      # language: DE
      
      
      @items = ( item1, item2, item3 );
      foreach filter in @selectedFilters {
        foreach item in @items {
          delete item from @items if filter.value != item.<filter.type>
          # or <, >, whatever
        }
      }
      
      return @items
      

      【讨论】:

        猜你喜欢
        • 2014-02-23
        • 2021-06-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-03-11
        • 2019-12-12
        • 2014-08-04
        • 1970-01-01
        相关资源
        最近更新 更多