欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 焦点 > vue2踩坑记录:computed中不建议调用后台接口

vue2踩坑记录:computed中不建议调用后台接口

2025/3/1 14:28:05 来源:https://blog.csdn.net/l_q_l/article/details/141607353  浏览:    关键词:vue2踩坑记录:computed中不建议调用后台接口

前言

在之前的博文vue2学习笔记11-深入学习监视属性并与计算属性对比中曾经提到:

1. computed能实现的watch都能实现。

2. watch能实现的,computed不一定能实现,如:在watch中可执行异步任务

对于第二点,其实是不太理解的,为什么在computed中不能执行异步任务呢?watch中执行异步任务又是什么意思呢?

今天,因需求,在computed中调用后台接口,就发现,它未等待接口返回,便自行返回了,然后,我的下一步操作因未拿到需要的参数而失败。

需求

点击某按钮的时候,需要从后台获取配置数据。因为是配置数据,所以一旦获取到,就不再会变化了,也就是说,我获取一次就可以。但是不想放到created里面做初始化,因为用户可能不点击这个按钮,所以不想页面打开的时候向后台发送那么多请求。

错误使用computed

所以,我把这些配置信息放到computed里面:

computed:{objRole(){let role = {};getRole(this.frm.deptId,this.roleKey).then(response => {if (response.code === 200) {role.roleId = response.data.roleId;role.roleName = response.data.roleName;}});return role;},
}

希望等用户点击这个按钮,产生调用的时候就去后台获取:

onBtnClick(){    getList(this.objRole);  //使用objRole作为参数的其它接口
}

然而执行的时候发现:

  1. 第一次点击的时候,getRole执行成功,getList提示bad request,查看payload信息,是undefined.
  2. 第二次点击:不再执行getRole,仅执行getList,且成功。

分析原因,因为第一次点击的时候,computed里面的getRole尚未返回,就开始执行下一个getList了。(js的异步真是好复杂。。。)

改用watch-仍不理想

想到本文开篇的那个提示,于是将getRole放到watch中

watch: {    'Frm.deptId'(newVal){getRole(newVal,this.roleKey).then(response => {if (response.code === 200) {this.objRole.roleId = response.data.roleId;this.objRole.roleName = response.data.roleName;}});
}

同时,在data中定义objRole:

data() {return {objRole:{}}
}

这样,在deptId发生变化时,执行一次getRole。但是因为deptId是页面初始化时候的参数,所以效果与放到created里面做初始化一样,在页面打开时发送了许多可能后面不需要的请求。

watch2:增加一个是否点击过的标志位isObjRoleClicked

初始状态为false

data() {return {objRole:{},isObjRoleClicked: false}
}

点击时置为true 

onBtnClick(){  this.isObjRoleClicked = true;  getList(this.objRole);  //使用objRole作为参数的其它接口
}

 监视,当值从false 变为 true的时候,获取数据

watch: {    'isObjRoleClicked'(newVal,oldVal){if(newVal && !oldVal){getRole(this.frm.deptId,this.roleKey).then(response => {if (response.code === 200) {this.objRole.roleId = response.data.roleId;this.objRole.roleName = response.data.roleName;}});}
}

此时,问题与使用computed相同,都未等待后台接口结束就返回了,导致下一个接口没有拿到参数,执行失败。

改用method,自己约定调用时机

于是,再一次修改,直接写在method中,点击按钮时触发,且触发时判断objRole是否已经有值,如果已经有内容了,就不再请求:

onBtnClick(){if(!this.objRole.roleId) {//第一次点击,尚未赋值,后台获取数据getRole(this.frm.deptId, this.roleKey).then(response => {if (response.code === 200) {this.objRole.roleId = response.data.roleId;this.objRole.roleName = response.data.roleName;getList(this.objRole);}});}else {//已经获取过数据了,不再重新获取getList(this.objRole);}
}

总结:

  1. 使用computed,不会等待其中的异步任务结束就会返回,导致后面使用computed中变量的地方拿不到预期值
  2. 使用watch,同样不会等待异步任务结束才返回。但是按照网上的说法,使用promise, async, wait等等应该是可以实现的,这部分我还不会。。。
  3. 使用method,完全实现了我最开始的想法:
  • 需要时才调用;
  • 调用过一次就不再调用

从性能上来说,这样处理或许能减轻重复调用给数据库带来的压力,也能避免在页面初始化时请求过多或许后面根本不需要的数据。

但是从代码的逻辑上,感觉应该还是用watch条理更清晰些,也更符合VUE的机制。还需要继续学习。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词