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

Vue删除数组元素后计算属性filteredUsers不更新表格问题求助

搞定Vue表格删除后不更新的问题

嘿,我一眼就看出问题出在哪了——你直接修改了Vue的props数组,这可是踩了单向数据流的坑啊!咱们一步步来解决:

为啥直接改this.users没用?

Vue的props是单向绑定的:父组件传过来的users,子组件只能读不能直接改。你在updateUserTable里用splice改的只是子组件里的副本,父组件的原始数据根本没变化,那依赖users的filteredUsers自然不会重新计算,表格当然没反应啦。而且直接改props本身就不符合Vue的设计规范,容易引发各种奇怪的bug。

正确的姿势:让父组件动手改数据

按照Vue的规矩,子组件要改父组件的数据,得通过触发自定义事件通知父组件,让父组件自己修改原始数据源。这样父组件的users更新后,子组件的props会自动同步,filteredUsers也会重新计算,表格就跟着刷新了。

下面是修改后的完整代码,我还加了几个优化点:


修改后的子组件代码

<script>
export default {
  name: 'search-user-component',
  props: ['users'],
  data() {
    return {
      search: '',
    }
  },
  computed:{
    filteredUsers: function() {
      const searchKeyword = this.search.toUpperCase();
      // 把match换成includes,更适合简单的字符串包含检查
      return this.users.filter((user) => {
        return user.name.toUpperCase().includes(searchKeyword) || user.email.toUpperCase().includes(searchKeyword);
      })
    }
  },
  methods: {
    deleteUser(user) {
      if (confirm("Are you sure?")) {
        $.ajax({
          type: 'post',
          data: {_method: 'delete'},
          url: "/admin/users/delete/" + user.id,
          // 用箭头函数替代bind(this),更简洁
          success: (result) => {
            if(!result.success){
              alert(result.message);
            } else {
              // 触发自定义事件,把要删除的用户传给父组件
              this.$emit('user-deleted', user);
            }
          },
          error: (result) => {
            console.log(result);
          }
        })
      }
    }
  }
}
</script>
<template>
  <div>
    <div class="box box-primary">
      <div class="box-body">
        <div class="form-group">
          <label for="usr">Search user</label>
          <input type="text" class="form-control" v-model="search">
        </div>
        <table class="table table-bordered table-hover">
          <thead >
            <th >ID</th>
            <th>Name</th>
            <th>E-mail</th>
            <th>Mobile phone</th>
            <th>Title</th>
            <th>Role</th>
            <th></th>
          </thead>
          <tbody>
            <!-- 添加:key是列表渲染的最佳实践,提升性能 -->
            <tr v-for="user in filteredUsers" :key="user.id">
              <td>{{ user.id }}</td>
              <td><a :href="'/admin/users/' + user.id ">{{ user.name }}</a>
              </td>
              <td>{{ user.email }}</td>
              <td>{{ user.phone}}</td>
              <td>{{ user.title }}</td>
              <td>{{ user.role.name }}</td>
              <td class="text-center">
                <button class="btn btn-sm btn-danger" @click="deleteUser(user)">delete</button>
              </td>
            </tr>
          </tbody>
        </table>
      </div>
    </div>
  </div>
</template>

父组件需要做的修改

在父组件使用这个子组件的时候,要监听我们触发的user-deleted事件,然后修改自己的用户数组:

<template>
  <div>
    <search-user-component 
      :users="userList"
      @user-deleted="removeUserFromList"
    ></search-user-component>
  </div>
</template>

<script>
import SearchUserComponent from './SearchUserComponent.vue';

export default {
  components: { SearchUserComponent },
  data() {
    return {
      userList: [] // 这是父组件的原始用户数据
    }
  },
  methods: {
    removeUserFromList(deletedUser) {
      // 找到要删除的用户索引,用splice删除(响应式更新)
      const targetIndex = this.userList.findIndex(user => user.id === deletedUser.id);
      if (targetIndex !== -1) {
        this.userList.splice(targetIndex, 1);
        // 也可以用返回新数组的方式,同样支持响应式:
        // this.userList = this.userList.filter(user => user.id !== deletedUser.id);
      }
    }
  },
  // 初始化获取用户列表的逻辑
  mounted() {
    // this.loadUsers();
  }
}
</script>

几个额外的小优化

  1. 把match换成了includes:match是用来做正则匹配的,这里只是检查字符串是否包含关键词,includes更高效也更直观。
  2. 给v-for加了:key="user.id":这是Vue列表渲染的必须项,能帮助Vue更高效地追踪每个列表项,避免不必要的DOM更新。
  3. 用箭头函数替代了bind(this):箭头函数会自动继承外部的上下文,不用手动绑定,代码更清爽。
  4. 去掉了location.reload():完全没必要刷新页面,通过Vue的响应式更新就能实现无刷新更新表格。

内容的提问来源于stack exchange,提问作者J.Wennergren

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:19:42