版本信息: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),用户从列表中选择bb
和cc
。现在,v-list-item-group
的模型selectedItems
包含 2 个选定的项目bb
和cc
,完美!但是,当用户在显示过滤器中输入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 资源都说同样的事情 - 将内部组件的value
props 绑定到自定义组件的value
props。然而,我刚刚发现这只是其中一种方法,而不是必须的。随着这种新的学习,我脑海中出现了更多的可能性,其中一种将我引向以下解决方案。
溶液:
将自定义组件值与底表列表分离
- 将内部
v-autocomplete
的模型绑定到数组数据,比如internalValue
。(为了简化起见,此内部组件不包含在有问题的模板中) - 将内部
v-list-item-group
模型(在底表中)绑定到单独的数据,例如bottomSheetSelections
。
根据底表中的用户操作更新自定义组件值
- 将观察程序添加到数组
bottomSheetSelections
:- 如果数组增长,则表示用户选择了更多项目。我们应该将附加项目推送到
internalValue
. - 如果阵列缩小:
- 如果缺少的项目仍然存在
filteredChoices
中,则删除是由用户取消选择触发的。我们应该从internalValue
中删除此项目。 - 否则,我们认为删除是由列表过滤器触发的。无需执行任何操作。
- 如果缺少的项目仍然存在
- 如果数组增长,则表示用户选择了更多项目。我们应该将附加项目推送到
在清除过滤器时恢复底部表中的用户选择
- 为
filteredChoices
添加观察程序。每当数组增长时,如果internalValue
中存在额外的选择,我们应该将其推送到bottomSheetSelections
。
总结
- 严格来说,这并不能解决问题标题的问题 - 底部表中的列表选择(绑定到
v-list-item-group
)仍在重置。但是,至少我们能够在清除过滤器的底部恢复它。 - 更重要的是,该解决方案实现了问题细节中提到的目标 - 保留用户选择值。我们将其保存在单独的数据
internalValue
中。 - 我还没有用一长串数据测试这个解决方案。我的直觉是,可能有更有效的解决方案。如果您有更好的解决方案,请分享它。