防止列表显示筛选器重置垂直列表选择



版本信息:Vuetify 2.6.3, Vue 2.6.14, Nuxt 2.15.8

我正在制作一个自定义组件,它应该与v-autocomplete有些相似,只是它被渲染为底表。如果用户在v-text-field中输入显示过滤器,选项列表(v-list)应该只显示那些与过滤器匹配的选项。

总的来说,除了一个用例外,它工作正常:假设列表有 5 个项目(aa、bb、cc、dd、ee),用户从列表中选择bbcc。现在,v-list-item-group的模型selectedItems包含 2 个选定的项目bbcc,完美!但是,当用户在显示过滤器中输入b时,已选择的项目cc将自动从selectedItems中删除。我无法判断selectedItems更改是由过滤器还是用户选择引起的。有没有办法在模型中维护选择?

我正在考虑一个黑客 - 如果选择了某个项目,即使它与过滤器不匹配,也要将其保留filteredChoices。这种行为是可以忍受的,但用户体验方面不如v-autocomplete过滤器那么直观。

简化的结构如下所示:

<template>
<v-bottom-sheet scrollable>
<v-card>
<v-card-text>
<v-list>
<v-list-item-group
v-model="selectedItems"
:mandatory="!optional"
:multiple="multiple"
>
<v-list-item
v-for="item in filteredChoices"
:key="item.value"
:value="item"
>
</v-list-item>
</v-list-item-group>
</v-list>
</v-card-text>
<v-text-field
v-model="filterInput"
placeholder="filter choices..."
hide-details
></v-text-field>
</v-card>
</v-bottom-sheet>
</template>
<script>
...
filteredChoices() {
if (this.filterInput == null) {
return this.allItems
}
return this.allItems.filter((item) => {
return item.label
.toLocaleLowerCase()
.includes(String(this.filterInput).toLocaleLowerCase())
})
},
...
</script>

我如何找到解决方案:

我对前端的东西很陌生。以前,当我学习如何实现对自定义组件v-model支持时,我遇到的所有 Web 资源都说同样的事情 - 将内部组件的valueprops 绑定到自定义组件的valueprops。然而,我刚刚发现这只是其中一种方法,而不是必须的。随着这种新的学习,我脑海中出现了更多的可能性,其中一种将我引向以下解决方案。

溶液:

将自定义组件值与底表列表分离

  1. 将内部v-autocomplete的模型绑定到数组数据,比如internalValue。(为了简化起见,此内部组件不包含在有问题的模板中)
  2. 将内部v-list-item-group模型(在底表中)绑定到单独的数据,例如bottomSheetSelections

根据底表中的用户操作更新自定义组件值

  1. 将观察程序添加到数组bottomSheetSelections
    • 如果数组增长,则表示用户选择了更多项目。我们应该将附加项目推送到internalValue.
    • 如果阵列缩小:
      • 如果缺少的项目仍然存在filteredChoices中,则删除是由用户取消选择触发的。我们应该从internalValue中删除此项目。
      • 否则,我们认为删除是由列表过滤器触发的。无需执行任何操作。

在清除过滤器时恢复底部表中的用户选择

  1. filteredChoices添加观察程序。每当数组增长时,如果internalValue中存在额外的选择,我们应该将其推送到bottomSheetSelections

总结

  1. 严格来说,这并不能解决问题标题的问题 - 底部表中的列表选择(绑定到v-list-item-group)仍在重置。但是,至少我们能够在清除过滤器的底部恢复它。
  2. 更重要的是,该解决方案实现了问题细节中提到的目标 - 保留用户选择值。我们将其保存在单独的数据internalValue中。
  3. 我还没有用一长串数据测试这个解决方案。我的直觉是,可能有更有效的解决方案。如果您有更好的解决方案,请分享它。

最新更新