Vue.js中输入事件更新shifts属性后无法恢复原始数据的问题
问题描述
我做了一个搜索输入框用来过滤数据,预期输入变化时会更新shifts数据对象,渲染过滤后的结果。测试时发现,只打印过滤结果filteredData是正常的:输入关键词能过滤出匹配数据,清空搜索能返回原始shifts。但一旦把filteredData赋值给this.shifts,就出现问题了:过滤后的数据能正常显示,但清空搜索时,shifts还是停留在之前的过滤结果,无法恢复原始数据。
正常打印过滤结果的代码
JavaScript
new Vue({ el: "#app", data: { search_input: '', shifts: {"John":[{"user_id":193,"shift_hours":0}],"Rose":[{"user_id":194,"shift_hours":0}]}, }, methods: { searchInput() { const filteredData = Object.keys(this.shifts).reduce( (obj, key) => { if ( key.toLowerCase().includes(this.search_input.toLowerCase()) ) { obj[key] = this.shifts[key]; } return obj; }, {} ); console.log(filteredData); } } })
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script> <div id="app"> <input v-model="search_input" @input.prevent="searchInput" type="text"/> </div>
出现问题的代码(赋值后无法恢复原始数据)
JavaScript
new Vue({ el: "#app", data: { search_input: '', shifts: {"John":[{"user_id":193,"shift_hours":0}],"Rose":[{"user_id":194,"shift_hours":0}]}, }, methods: { searchInput() { const filteredData = Object.keys(this.shifts).reduce( (obj, key) => { if (key.toLowerCase().includes(this.search_input.toLowerCase())) { obj[key] = this.shifts[key]; } return obj; }, {} ); this.shifts = filteredData; } } })
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script> <div id="app"> <input v-model="search_input" @input.prevent="searchInput" type="text" /> <pre>{{ shifts }}</pre> </div>
问题原因
核心问题是你每次过滤都是基于当前的this.shifts,而一旦将过滤后的数据赋值给this.shifts,原始数据就被覆盖了。举个例子:
- 输入"John",过滤后
shifts变成只有John的对象; - 清空搜索时,你是基于已经只剩John的
shifts来过滤,自然只能得到John的数据,无法恢复包含Rose的原始数据。
解决方案
保留一份原始数据的副本,过滤操作始终基于原始数据,而不是被修改后的shifts。这里提供两种实现方式:
方式一:修改原有方法逻辑
在data中新增originalShifts存储原始数据,过滤时基于这份原始数据处理:
JavaScript
new Vue({ el: "#app", data: { search_input: '', shifts: {"John":[{"user_id":193,"shift_hours":0}],"Rose":[{"user_id":194,"shift_hours":0}]}, originalShifts: {"John":[{"user_id":193,"shift_hours":0}],"Rose":[{"user_id":194,"shift_hours":0}]} // 保存原始数据 }, methods: { searchInput() { const filteredData = Object.keys(this.originalShifts).reduce( (obj, key) => { if (key.toLowerCase().includes(this.search_input.toLowerCase())) { obj[key] = this.originalShifts[key]; } return obj; }, {} ); this.shifts = filteredData; } } })
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script> <div id="app"> <input v-model="search_input" @input.prevent="searchInput" type="text" /> <pre>{{ shifts }}</pre> </div>
方式二:使用Vue计算属性(更优雅)
利用计算属性自动响应依赖变化的特性,省去手动调用方法的步骤:
JavaScript
new Vue({ el: "#app", data: { search_input: '', originalShifts: {"John":[{"user_id":193,"shift_hours":0}],"Rose":[{"user_id":194,"shift_hours":0}]} }, computed: { shifts() { return Object.keys(this.originalShifts).reduce((obj, key) => { if (key.toLowerCase().includes(this.search_input.toLowerCase())) { obj[key] = this.originalShifts[key]; } return obj; }, {}) } } })
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script> <div id="app"> <input v-model="search_input" type="text" /> <pre>{{ shifts }}</pre> </div>
内容的提问来源于stack exchange,提问作者suo
相关产品推荐
相关产品推荐

