javascript - 检查多个选项并在 vuex 中进行过滤

标签 javascript vue.js vuejs2 vuex

我正在尝试过滤 vuex 存储中的数据。我可以做到,但不正确。如果我只选中一个选项,那么它会过滤并显示选中的项目。但是,当我选中多个选项时,它什么都不显示……

到目前为止我所做的就在下面。

已更新 codesandbox

在这里,完整的例子。这就是我面临的情况。 https://codesandbox.io/s/vue-template-oxwtk

filter.js

export function getByRooms(articles, room) {
    if (room.length == 0) {
        return articles;
    } else {
        return articles.filter(article => {
            if (article.rooms1.includes(room)) {
                return article;
            }
        })
    }
} 

store.js

在 store.js 中导入函数并使用它。

state: {
    articles: [],
    rooms: [],
},

mutations: {
    setArticles(state, articles){
        state.articles = articles;
    },
    setRooms(state, room){
        state.rooms = room;
    },
},
getters: {
    loadArticles(state){
        return state.articles;
    },

    // filters
    loadAllFilters(state){
        return getByRooms(state.articles, state.rooms);
    },
},

组件 并在组件中。我正在使用它。

<p>rooms</p>
<ul class="inputWrap checks">
    <li  :key="index" v-for="(item, index) in uniqueRoom">
        <vs-checkbox v-model="findRooms" :vs-value="item">{{item}}</vs-checkbox>
    </li>
</ul>

findRooms: {
    set(val){
        this.$store.commit("setRooms", val);
    },
    get(){
        return this.$store.state.articles.rooms;
    }
},

到目前为止,还不错。我可以检查并过滤它。但如果检查不止一个房间。它什么都不显示。虽然在 store.js 中状态 rooms:[] 是一个数组。所以我可以检查不止一个。但是当我检查第二个和更多的时候。清除 loadAllFilters 数据...

我有点卡在这里。也许这是一件简单的事情,但无法弄清楚这里的问题是什么。

最佳答案

我尝试使用您提供的代码编写了一个完整的示例:

function getByRooms(articles, rooms) {
  if (rooms.length === 0) {
    return articles;
  }
    
  return articles.filter(article => {
    return rooms.some(room => article.rooms1.includes(room))
  });
} 

const store = new Vuex.Store({
  state: {
    articles: [
      {rooms1: ['red', 'green', 'blue']},
      {rooms1: ['red']},
      {rooms1: ['yellow', 'green']},
      {rooms1: ['blue', 'yellow']},
      {rooms1: ['red', 'blue']}
    ],
    rooms: [],
  },

  mutations: {
    setArticles(state, articles){
      state.articles = articles;
    },
    setRooms(state, room){
      state.rooms = room;
    },
  },
  getters: {
    loadArticles(state){
      return state.articles;
    },

    // filters
    loadAllFilters(state){
      return getByRooms(state.articles, state.rooms);
    },
  }
});

new Vue({
  el: '#app',
  store,
  
  computed: {
    findRooms: {
      set(val){
        this.$store.commit("setRooms", val);
      },
      get(){
        return this.$store.state.rooms;
      }
    },
    uniqueRoom() {
      const rooms = {};
      
      for (const article of this.$store.state.articles) {
        for (const room of article.rooms1) {
          rooms[room] = true;
        }
      }
      
      return Object.keys(rooms);
    }
  }
});
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link href="https://unpkg.com/vuesax@3.9.0/dist/vuesax.css" rel="stylesheet">
<script src="https://unpkg.com/vue@2.6.10/dist/vue.js"></script>
<script src="https://unpkg.com/vuex@3.1.1/dist/vuex.js"></script>
<script src="https://unpkg.com/vuesax@3.9.0/dist/vuesax.umd.js"></script>
<div id="app">
  <p>rooms</p>
  <ul class="inputWrap checks">
    <li  :key="index" v-for="(item, index) in uniqueRoom">
      <vs-checkbox v-model="findRooms" :vs-value="item">{{item}}</vs-checkbox>
    </li>
  </ul>
  <ul>
    <li v-for="article in $store.getters.loadAllFilters">
      {{ article.rooms1 }}
    </li>
  </ul>
</div>

我假设文章必须只匹配一个选中的复选框,而不是所有复选框。如果您想匹配所有这些,只需将 rooms.some 更改为 rooms.every

这一行似乎是错误的:

return this.$store.state.articles.rooms;

我假设它应该是:

return this.$store.state.rooms;

主要更改是重写 getByRooms 以使用 some

另请注意,传递给 filter 的函数应该只返回一个 true/false 值以确定是否应包含某个项目.在您的原始代码中,您有这个:

if (article.rooms1.includes(room)) {
    return article;
}

返回 article 将被视为真值,但它与返回 true 一样有效。整个事情可以折叠为:

return article.rooms1.includes(room);

我对 getByRooms 的重写只是将其扩展为检查每个选定的房间,而不是假设只有其中一个房间。

更新:

现在您已经添加了 CodeSandbox 示例,它会更清楚发生了什么......

改变这一行:

if (car.color.includes(color)) {

为此:

if (color.includes(car.color)) {

或者更好:

return cars.filter(car => color.includes(car.color))

问题只是您将 colorcar.color 设置错了。

color 是一个数组,car.color 是一个字符串。字符串和数组都有一个 includes 方法。字符串版本会将参数隐式转换为字符串。因此,例如,这将是 true:

'red'.includes(['red'])

数组将使用 toString 转换为字符串,它只返回字符串 'red''red'.includes('red') true

如果有两个值,它会失败。这相当于:

'red'.includes(['red', 'purple'])

现在数组被转换为字符串'red,purple',所以它等价于'red'.includes('red,purple'),即错误

你真正想要的是相反的测试,实际上是这样的:

['red', 'purple'].includes('red')

关于javascript - 检查多个选项并在 vuex 中进行过滤,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57305052/

相关文章:

javascript - 从没有副作用的原型(prototype)函数创建有副作用(就地)的函数

javascript - 如何使用 id React Js 和 Firebase 显示数据

javascript - Vuejs 组件未响应 "mouseleave"事件

JavaScript PreventDefault 不起作用,也不返回 false;

javascript - 为什么html元素的innerText属性只显示body元素的innerText?

javascript - 在 Vue Webpack 中禁用转译器以更轻松地调试

javascript - 使用 django REST 和 Vue.js 传播不可迭代实例的无效尝试

javascript - Vue js 构建失败

javascript - Vuejs : Show confirmation dialog before route change

javascript - chart.js 动画结束回调