You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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,原始数据就被覆盖了。举个例子:

  1. 输入"John",过滤后shifts变成只有John的对象;
  2. 清空搜索时,你是基于已经只剩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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 11:45:27