我正在尝试过滤 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))
问题只是您将 color
和 car.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/