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>
几个额外的小优化
- 把
match换成了includes:match是用来做正则匹配的,这里只是检查字符串是否包含关键词,includes更高效也更直观。 - 给
v-for加了:key="user.id":这是Vue列表渲染的必须项,能帮助Vue更高效地追踪每个列表项,避免不必要的DOM更新。 - 用箭头函数替代了
bind(this):箭头函数会自动继承外部的上下文,不用手动绑定,代码更清爽。 - 去掉了
location.reload():完全没必要刷新页面,通过Vue的响应式更新就能实现无刷新更新表格。
内容的提问来源于stack exchange,提问作者J.Wennergren
相关产品推荐
相关产品推荐

