最近突然想起来在前公司做的一个业务场景,觉得挺有意思的,在这次优化的过程中也能对于Vue的生命周期有更深的理解。
1.原始的JSSDK介绍
JSSDK功能点介绍 我们做了一款JSSDK,内部的实现是在SDK加载的时候,会在当前页面创建一个iframe页面,在iframe页面会进行canvas等绘图(绘图会有时间损耗),获取一些信息,然后上报到服务器,在进行Vue集成到时候遇到一些问题,本身iframe信息采集也是需要耗时的,所以在采集完成的时候,SDK会回调一个函数callback,进行通知主页面;也提供了主动调用SDK的方法,
2.客户需求:
- 在应用的支付页面的时候首屏进行加载SDK,并且执行SDK的信息上报
- 并且在其他地方可以自主触发上报信息接口
- 使用vue框架进行集成,并且写出demo
3.技术分析:
- 由于JSSDK加载比较耗时,所以选择在集成的时候,在应用初始化的时候集成,避免需要重复集成
- 考虑到用户可能使用到懒加载,需要考虑在首页完整的执行机制
- JSSDK采集信息发送到服务器,是需要时间,需要进行控制,并且能准确的通知用户是否能进行重新生成sessionId
- 由于回调函数通知的时候,是全局的函数,所以回调函数做成一个回调队列,防止回调错乱
- 重新集成的时候(updateSessionID)需要判断当前的dom是否有指定ID的iframe
- 在app.vue页面进行初始化,在首屏页面需要等待初始化完成之后才可以进行首页的更新
4.实现思路
- 封装一个util/pagegis文件,对外暴露两个方法,init 、uploadSessionID
- init方法动态创建script标签,引入js,将callback的回调函数设置队列栈:callbackStack = {};key为当前生成的sessionId、value为回调函数Function;设置标志符:payegisKey
- update方法判断当前页面是否存在id为pagegis的iframe,以及 payegisKey,进而在判断是否是初始化还是执行更新的方法
(JSSDK封装集成业务流程图)
const appId = 'XXXXXXX'
const baseUrl = 'http://localhost:8080' // 此处是JSSDK 对应的后台地址
let lastRandomId = null
const payegisKey = 'payegis_is_init'
localStorage.setItem(payegisKey, false)
// 随机字符串
function randomString (len) {
len = len || 32
const $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678'
const maxPos = $chars.length
let pwd = ''
for (let i = 0; i < len; i++) {
pwd += $chars.charAt(Math.floor(Math.random() * maxPos))
}
return pwd
}
// push callback to stack
const callbackStack = {}
function updateSessionId (callback) {
if (localStorage.getItem(payegisKey) === 'false') return
lastRandomId = randomString(32) // 此处是再次随机生成Id, 也可以自主传参数
window.payegis.uploadSessionID(lastRandomId); // JSSDK 对外暴露的更新方法
if (callback) {
callbackStack[lastRandomId] = callback // 推栈
}
}
const payegis = {
// 设备指纹初始化
init (callback) {
const iframes = document.getElementsByTagName('iframe')
const arr = Array.from(iframes).map(item => item.getAttribute('id')) || []
if (arr.includes('payegisIfm')) {
this.uploadSessionID(callback, true)
return
}
if (localStorage.getItem(payegisKey) === 'false') {
window.isOk = function (res) {
if(localStorage.getItem(payegisKey) === 'false') {
localStorage.setItem(payegisKey, true)
}
if (callbackStack.hasOwnProperty(lastRandomId)) {
callbackStack[lastRandomId](res)
}
}
lastRandomId = randomString(32)
const ts = new Date().getTime() // 当前的时间戳
const url = `${baseUrl}/did/js/dp.js?appId=${appId}&sessionId=${lastRandomId}&ts=${ts}&callback=isOk`
// 动态生成js标签
const script = document.createElement('script')
script.type = 'text/javascript'
script.src = url
document.body.append(script)
if (callback) {
callbackStack[lastRandomId] = callback
}
} else {
console.log('payegis is initialized')
}
},
// 重新生成设备指纹
uploadSessionID (callback, isCheck = false) {
let arr = []
if (!isCheck) {
const iframes = document.getElementsByTagName('iframe')
arr = Array.from(iframes).map(item => item.getAttribute('id')) || []
}
if (isCheck || (arr.includes('payegisIfm') && localStorage.getItem(payegisKey) === 'true')) {
updateSessionId(callback)
} else {
this.init(callback)
}
}
}
export default payegis
5.vue应用初始化和首页初始化的加载机制
1.路由正常加载执行顺序
2.路由懒加载执行顺序
3.疑问: 我用vue-cli初始化项目加载顺序是上述,但是我用ruo-yi框架的vue前端使用懒加载和不使用懒加载,加载顺序都是第二种,这个问题未搞明白,要是有大佬清楚,可以在评论区评论。。
写在最后
我是crazyu,一位前端开发工程师。
- 文中如有错误,欢迎在评论区指正,如果这篇文章帮到了你,欢迎点赞和关注😊
- 本文首发于微信公众号:crazyu 前端,未经许可禁止转载