Vue.js前后页按钮异常:首次点击URL更新但数据不加载
解决Vue.js + Laravel SPA中首次点击上/下一页按钮数据不更新的问题
我太懂你遇到的这个坑了——首次点上一页或下一页,URL明明变了但页面数据纹丝不动,第二次点击就正常了对吧?这问题根源出在路由跳转的异步特性上,咱们一步步把它搞定。
问题原因分析
你现在的代码逻辑是:调用this.$router.push()跳转路由后,立刻执行this.loadCandidateProfileData()。但路由跳转是异步操作,push方法刚执行完时,this.$route.params.itemId还是原来的旧值,所以loadCandidateProfileData()加载的还是之前的数据。第二次点击时,路由已经完成更新,参数是新的了,数据自然就正常加载了。
解决方案
方案1:等待路由跳转完成后再加载数据
利用$router.push()返回的Promise,等路由完全跳转成功后再调用数据加载方法,确保拿到最新的路由参数:
nextCandidate: async function() { try { const itemId = this.$route.params.itemId; const response = await employerService.loadCandidateProfileData(itemId); this.nextRecord = response.data.next_record; // 等待路由跳转完成 await this.$router.push(`/employer/search/filter-by/${this.nextRecord.id}/show`); // 此时路由参数已更新,再加载新数据 this.loadCandidateProfileData(); } catch(error) { this.$toast.error(error.response.data.message); } }, previousCandidate: async function() { try { const itemId = this.$route.params.itemId; const response = await employerService.loadCandidateProfileData(itemId); this.previousRecord = response.data.previous_record; await this.$router.push(`/employer/search/filter-by/${this.previousRecord.id}/show`); this.loadCandidateProfileData(); } catch(error) { this.$toast.error(error.response.data.message); } }
方案2:监听路由参数变化自动加载数据(更推荐)
这是更符合SPA路由驱动数据的最佳实践——把路由变化和数据加载解耦,不管是通过按钮跳转还是直接修改URL,只要itemId参数变了,就自动加载对应数据:
- 给组件添加路由参数监听:
watch: { // 监听itemId参数的变化 '$route.params.itemId': function(newItemId) { // 参数更新时自动加载新数据 this.loadCandidateProfileData(); } }, // 页面首次挂载时加载初始数据 mounted() { this.loadCandidateProfileData(); }
- 修改按钮方法,去掉手动调用
loadCandidateProfileData()的代码:
nextCandidate: async function() { try { const itemId = this.$route.params.itemId; const response = await employerService.loadCandidateProfileData(itemId); this.nextRecord = response.data.next_record; this.$router.push(`/employer/search/filter-by/${this.nextRecord.id}/show`); } catch(error) { this.$toast.error(error.response.data.message); } }, previousCandidate: async function() { try { const itemId = this.$route.params.itemId; const response = await employerService.loadCandidateProfileData(itemId); this.previousRecord = response.data.previous_record; this.$router.push(`/employer/search/filter-by/${this.previousRecord.id}/show`); } catch(error) { this.$toast.error(error.response.data.message); } }
这种方式不仅能解决你当前的问题,还让代码结构更清晰,后续维护起来更省心。
内容的提问来源于stack exchange,提问作者Ryan Sacks
相关产品推荐
相关产品推荐

