Vue.js单文件应用:Ajax响应后删除数组项的异步问题求助
从jQuery转Vue的新手?这两个核心问题帮你搞定!
刚从jQuery转Vue确实会有不少思维上的转换阵痛,我当初也踩过类似的坑,先帮你拆解一下问题,然后给你最优雅的解决方案:
核心问题1:异步删除时索引错乱
你说得对,用post.id定位是最佳方案——因为索引会随着数组项的删除/插入动态变化,而id是每个帖子的唯一标识,永远不会变。
核心问题2:动态添加isLoading不生效
Vue默认无法检测对象新增的属性(这是响应式原理的限制),你之前用splice强制更新的方式确实不优雅,正确的做法是用this.$set(Vue实例上的方法)来给帖子对象添加响应式属性。
修改后的完整代码
JavaScript部分
window.app = new Vue({ el: '#app', data: { name: '', posts: [], }, created() { this.fetchData(); }, methods:{ fetchData() { axios.get('https://jsonplaceholder.typicode.com/posts').then(response => { // 给每个帖子初始添加isLoading属性,确保响应式 this.posts = response.data.slice(0,20).map(post => ({ ...post, isLoading: false })); }); }, removeItem(post) { // 用this.$set添加响应式属性,无需splice hack this.$set(post, 'isLoading', true); axios.post('//jsfiddle.net/echo/json/', "json='{status:success}'&delay=2") .then(() => { // 用id过滤数组,精准删除对应项,彻底避开索引问题 this.posts = this.posts.filter(item => item.id !== post.id); }) // 别忘了处理请求失败的情况,恢复按钮状态 .catch(() => { this.$set(post, 'isLoading', false); }); } }, computed: { showAlert() { return this.name.length > 4 ? true : false } } })
HTML部分(仅确保key用唯一id)
<div id="app"> <div v-for="post in posts" :key="post.id"> <b-card class="mb-2"> <b-card-title>{{post.title}}</b-card-title> <b-card-text>{{post.body}}</b-card-text> <a href="#" @click.prevent="removeItem(post)" class="card-link"> Remove <span v-show="post.isLoading" class="spinner"></span> </a> </b-card> </div> </div>
关键改动说明
- 初始化时统一添加
isLoading:在获取帖子数据后,用map给每个帖子加上isLoading: false,让属性从一开始就是响应式的,后续直接修改也能触发视图更新。如果不想初始化时加,用this.$set动态添加也是完全可行的。 - 用
filter代替splice删除项:filter会返回排除目标项的新数组,不管数组之前有没有其他项被删除,都能精准匹配id删除目标帖子,彻底避免索引错乱的问题。 - 添加错误处理逻辑:异步请求可能失败,所以要在
catch回调里把isLoading改回false,避免按钮一直显示加载状态。
思维转换小提示
jQuery是直接操作DOM和元素索引,而Vue是数据驱动视图——你只需要管好数据的变化,视图会自动同步更新。以后处理这类问题时,先想“我该怎么修改数据”,而不是“我该怎么操作DOM/索引”,慢慢就会适应Vue的思维模式啦~
内容的提问来源于stack exchange,提问作者Miro
相关产品推荐
相关产品推荐

