vue项目created()被调用多次的坑
Posted 追逐梦想永不停
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vue项目created()被调用多次的坑相关的知识,希望对你有一定的参考价值。
一、问题描述
最近碰到一个奇怪的生产问题:
正常情况下、前端页面会请求一次后台、然后后台返回信息("处理成功"
或"处理失败"
)、前端展示;
后台用aop+redis写了一个防止重复调用的方法,如果5s内同一个用户重复调用同一个接口,就返回"请勿重复调用"
,前端就会展示这个。
但是,某几个页面,前端总是会重复调用后端2次,导致用户只能看到"请勿重复调用"
,无法确认本次操作是成功还是失败,严重影响了用户的正常使用。(虽然是处理成功,但是显示不出来…)
一开始还怀疑是不是后端的问题,排查了半天,终于锁定了,是前端的问题,vue项目中的created()
方法被调用了2次
。
继续排查,发现从正常页面跳转到这个问题页面时,确实只跳转了1次,按理说created()方法应该也只触发1次的,但是就是不知道为什么触发了2次。
二、排查过程
1.从头开始排查前端项目,vue项目首先会加载main.js,发现这个文件里有:
import Vcon from './assets/js/vcon'
new Vcon(
env: ENV
, () =>
new Vue(
router,
render: h => h(App)
).$mount('#app')
)
发现这个文件里,并不是普通的使用new Vue()
创建的页面,而是外面有封装了一个new Vcon()
方法,并传了2个参数,其中第一个参数是 env: ENV
,第二个参数是 () => new Vue( router, render: h => h(App) ).$mount('#app')
2.继续,查看./assets/js/vcon.js
文件,发现这个文件里有类似这样的:
class Vcon
constructor (opt, callBack)
this.env = opt.env || '' // 记录代码环境
this.callBack = callBack // 记录回调函数
// 如果是生产环境
if (this.env !== 'test')
this.prodInit()
typeof this.callBack === 'function' && this.callBack()
return
// 如果是测试环境
if (this.env === 'test')
this.testInit()
return
testInit ()
import('vconsole').then(( default: VConsole ) =>
new VConsole()
console.log('测试vconsole加载完成')
typeof this.callBack === 'function' && this.callBack()
)
prodInit ()
let _that = this
window.ISALES.callApp('getUserInfoByNative',
callback: function (userInfo)
if (userInfo.code === '0')
_that.betterStaffNUmber = userInfo.msg.staffNumber
_that.betterHandler(userInfo)
return
alert('获取sdk出错,请稍后再试')
)
betterHandler (userInfo)
if (userInfo.msg.userCode == 'admin')
import('vconsole').then(( default: VConsole ) =>
new VConsole()
console.log(`admin的vconsole加载完成`)
typeof this.callBack === 'function' && this.callBack()
)
return
else
this.callBack()
其中,当上一步执行new Vcon()
时,实际执行的就是这里的constructor ()
方法;
如果是测试环境,那就执行testInit ()
方法,这个还是比较明显的,用来展示vconsole(测试环境一直正常,没有复测出来问题);
如果是生产环境,那就执行prodInit()
方法,然后执行typeof this.callBack === 'function' && this.callBack()
方法(这里感觉有些问题,先继续看);
prodInit()
方法里,会执行window.ISALES.callApp
方法,这个是个sdk方法(这个前端项目是vue项目,可以打包后把静态页面部署在服务器上;sdk方法是app和ios里的方法,前端只能这样才能调用到、待sdk方法处理完后会触发callback方法);
sdk方法中,会执行betterHandler()
方法,意思是,如果当前app/ios的登录人是admin,那就显示vconsole,否则就不显示。
3.根据生产created()方法被调用2次、而测试正常的现象,排查到问题方法位置:
// 如果是生产环境
if (this.env !== 'test')
this.prodInit()
typeof this.callBack === 'function' && this.callBack()
return
因为prodInit()方法的逻辑中,正常情况下,已经调用过一次typeof this.callBack === 'function' && this.callBack()
了,然而执行完prodInit()方法后,又会调用一次typeof this.callBack === 'function' && this.callBack()
,所以才导致created()方法被重复调用了2次。
4.正确代码如下:
// 如果是生产环境
if (this.env !== 'test')
this.prodInit()
//这里导致了重复created()
//typeof this.callBack === 'function' && this.callBack()
return
修改后,发布生产,终于恢复了正常。
三、备注
1.vue项目中,有时会自动优化代码格式,导致if后面没有大括号、只有1句,满足条件就执行、不满足就不执行,需要注意。
2.有时,if没有else,而是if中结尾有个return,此时也类似else,但是容易忽略,需要注意。(这个也是自动优化格式的?还是故意写的难懂了?)
3.typeof this.callBack === 'function' && this.callBack()
,这个的意思是,如果this.callBack
是function
类型的,那就会执行后面的this.callBack()
方法,然后继续下一步;如果不是function
类型的,那就不执行后面的方法,直接继续下一步。(又一个不好理解的高级写法,用if不好吗?)
4.正常情况下,vue页面的created()方法会在页面初始化的时候执行1次;但是如果代码有问题,就会导致created()方法会在页面初始化的时候执行2次或多次(如本文),这个坑需要注意。
vue的生命周期 created mounted等
生命周期:
beforeCreate
在实例初始化之后,数据观测和event/watcher时间配置之前被调用
created
页面加载之前执行,在实例创建完成后被立即调用。执行顺序:父组件-子组件 可以执行多次 因为执行
created钩子函数的时候,页面还没有渲染出来,所以如果在此操作dom元素,一定会找不到相关元素,会报错。
在created 接受数据,然后$nextTick(function(){做swiper初始化}),
created的时候data数据生成了,可以把数据挂载到vue的data上面了。vue请求初始化数据放在这里
beforeMount
在挂载开始之前被调用
mounted
页面加载完成后执行。执行顺序:子组件-父组件 在mounted里面的都是钩子函数 可以直接操作dom节点 生命周期--钩子 页面初始化
mounted在整个vue实例的生命周期中只执行一次!!在页面第一次加载完成后才会被调用出来。在mounted中发起后端请求,拿回数据,配合路由钩子做一些事情。
beforeUpdate
updated
activated
deactivated
beforeDestroy
destroyed
errorCaptured
watch:watch是去监听一个值的变化,然后执行相对应的函数。
computed:computed是计算属性,也就是依赖其它的属性计算所得出最后的值
以上是关于vue项目created()被调用多次的坑的主要内容,如果未能解决你的问题,请参考以下文章