vue.js checkbox v-model只返回数组中的第一个关键字

cld4siwp  于 2023-04-07  发布在  Vue.js
关注(0)|答案(1)|浏览(142)

我在一个数组中有几个曲目,并有一个搜索和复选框来过滤曲目。然而,复选框只返回每个过滤器中的第一个识别字符串。因此,如果我单击pop的复选框-在下面的示例中-它将只显示仅包含流行流派的曲目。包含摇滚,流行流派的曲目不会出现。这是在Vue的composition API中。
以下是脚本:

const searchTerm = ref('')

const genreFilter = ref([])
const moodsFilter = ref([])
const tempoFilter = ref([])
const themeFilter = ref([])

const filteredTracks = computed(() => {
let filtered = useSong.tracks;

if (searchTerm.value) {
const term = searchTerm.value.toLowerCase();
filtered = filtered.filter(track =>
  track.description.toLowerCase().includes(term) || 
  track.genre.toLowerCase().includes(term) ||
  track.keywords.toLowerCase().includes(term) ||
  track.moods.toLowerCase().includes(term)
);
}

if (genreFilter.value.length > 0) {
filtered = filtered.filter(track => genreFilter.value.includes(track.genre))
}

if (moodsFilter.value.length > 0) {
filtered = filtered.filter(track => moodsFilter.value.includes(track.moods))
}

if (tempoFilter.value.length > 0) {
filtered = filtered.filter(track => tempoFilter.value.includes(track.tempo))
}

if (themeFilter.value.length > 0) {
filtered = filtered.filter(track => themeFilter.value.includes(track.theme))
}

return filtered;
});

下面是HTML:

<div class="genres w-1/4"><h1 class="font-bold text-[#aeaeae]">Genres</h1><br>
        <input class="css-checkbox" type="checkbox" id="Rock" key="genre" value="Rock" v- 
 model="genreFilter">
        <label class="css-label pl-2 text-s font-light text-[#aeaeae]" for="Rock">Rock</label> 

        <input class="css-checkbox" type="checkbox" id="Pop" key="genre" value="Pop" v- 
 model="genreFilter">
        <label class="css-label pl-2 text-s font-light text-[#aeaeae]" for="Pop">Pop</label>

我如何修改它,以便我可以选中多个流派框,并让它们全部显示,只删除未选中的框。任何帮助都将不胜感激。此外,你会注意到,在过滤器中,我有一个用于情绪,克里思和主题。每当我点击这些复选框中的任何一个时,数组中没有显示任何内容,尽管数组具有匹配的情绪,节奏和主题。谢谢。

8qgya5xd

8qgya5xd1#

genreFilter变量是一个数组:

const genreFilter = ref([])

但是你把整个事情放在复选框的v-model中:

<input type="checkbox" value="Rock" v-model="genreFilter">

有效地用字符串代替数组。
所以当你这么做的时候

filtered = filtered.filter(track => genreFilter.value.includes(track.genre))

您调用的不是Array.prototype.includes(),而是String.prototype.includes()。这可以工作,但不是您想要的。
简单的解决方案是在复选框中使用索引:

<input type="checkbox" value="Rock" v-model="genreFilter[0]">

一个可能更好的解决方案是在选中复选框时添加或删除元素:

<input type="checkbox" value="Rock" @change="updateGeneres($event.target)">

const updateGenres = ({value, checked}) => checked 
? (genreFilter.value.includes(value) || genreFilter.value.push(value))
: (genreFilter.value = genreFilter.value.filter(g => g !== value))
const { createApp, ref, computed} = Vue;

const App = {
  setup(){
    const genres = ['Rock', 'Pop']
    const genreFilter = ref([])
    const updateGenres = ({value, checked}) => checked
      ? (genreFilter.value.includes(value) || genreFilter.value.push(value))
      : (genreFilter.value = genreFilter.value.filter(g => g !== value))
    const items = [
      {genre: 'Pop', title: 'This is Pop'},
      {genre: 'Rock', title: 'This is Rock'},
      {genre: 'Something Else', title: 'This is something else'},
    ]
    const filteredItems = computed(() => genreFilter.value.length === 0 ? items : items.filter(i => genreFilter.value.includes(i.genre) ))
    return {genres, genreFilter, updateGenres, filteredItems}
  },
}
const app = createApp(App)
app.mount('#app')
<div id="app">
  
  <div v-for="genre in genres">
    <label>
      <input
        type="checkbox" 
        :value="genre" 
        @change="updateGenres($event.target)"
      > {{ genre }}
    </label>
  </div>
  
  Selected Genres: {{genreFilter}}
  
  <ul>
    <li v-for="item in filteredItems">{{ item.title }}</li>
  </ul>
  
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>

下面是SFC中的安装脚本片段

相关问题