##懵懵懂懂也敲了三年的代码了,今天心血来潮开始记录我第一篇文章。
##前言:
很不幸,我作为一个Java后端开发,也是需要写前端功能我,而我对于前端的知识还处于大学时期老师传授给我html\css\javascript的,那么问题来了?为啥是我来做这个功能。这件事还得是从被经理叫去问话开始,经理指着这个一个旧系统和一个新系统说:我想这个新系统的菜单点击后可以跳转至旧系统,这个功能可以实现吗?
当然作为一个Java后端来说,实现功能肯定得从需求分析开始:新系统属于旧系统的重构开发,旧系统前端页面使用了ExtJs框架,新系统已VUE+Element-UI架构进行开发,新系统菜单需要平迁旧系统菜单,可是旧系统菜单好几百个菜单页面,一次性迁移肯定弄不完,于是乎,就有了这个奇怪的需求,在新系统点击菜单跳转至旧系统的菜单页面。(奇怪的需求就是这样来的。。。开发真头疼)
需求分析完了,这时候就要考虑方案的实现了:
新旧系统归属于两个域名,这涉及到跨域问题了,而新系统的菜单页面点击事件要传递到旧系统,通过window.postMessage这个函数进行跨系统交互,只需要在旧系统复用菜单跳转方法即可实现,而身份验证通过token方式进行验证,调用链路非常短,响应非常迅速,于是这个方案就被我敲定了。
新系统菜单时需要 传递信息至 旧系统,若旧系统界面没打开那肯定接收不到,此时就需要通过window.open()方法进行页面的创建,创建成功后此时需要等待旧系统页面的初始化完成,在新系统中监听旧系统的回调函数,旧系统在初始化完成后往 新系统发送消息,并建立监听事件,在收到新系统的消息后进行身份信息的校验,旧系统作为新系统的子窗口,可以通过window.opener.postMessage()将消息推送至新系统中,此时新旧系统的交互问题已经解决了,剩下的只是一些业务信息的传递。
正当我松了一口气时,发现事情没这么简单,因为我们需要持续性往旧系统发送消息,那么这个window.open()生成的对象就需要全局共享,而这个对象因为是存储了跨域地址无法存储至session或cokie中,于是我便存储在了window.top 中 全局便可以取到同一个对象,此时需要通过window.closed方法进行判断对象是否存在,页面是否已经关闭,若已关闭则需要重新打开,没有关闭那就直接发送消息,消息发送完成后还需要聚焦页面,聚焦页面调用 window.focus()方法进行聚焦,我本以为聚焦页面应该没啥问题,结果测试时发现,仅仅只有顶层window创建页面时调用 focus()方法生效,而作为其他层级的window对象创建页面时调用 focus()无效。我本以为是因为对象没有调用到导致,但实际测试发现 window.colse()确实可以正常使用,查了很久资料,并没有该原因的说明,但是功能还是得实现的,于是乎只能调整代码统一使用 windo.top对象进行页面的打开。个人猜测,可能是基于浏览器安全策略考虑,只允许顶层窗口进行focus()方法的调用。
opentab(){
let oldTab = window.top.tab
if(oldTab||oldTab.colsed){
oldTab = window.top.open("http://wwww.test.com");
}
//添加顶层页面的监听事情
window.top.tab.addEventListener("message", function(params){
if(params.url == 'demo'){
//可以选择跳转页面url
oldTab.postMessage("test", "*");
//消息发送完成后聚焦旧系统页面
oldTab.focus();
});
let inval =setInterval(function(){
if(oldTab.closed){
console.log('old页面已关闭');
//去除页面的监听事件
oldTab.removeEventListener();
//销毁定时器
clearInterval(inval);
}
},100);
window.top.tab = oldTab;
}
//旧系统消息监听
listenNewTab(){
window.addEventListener("message", function(params) {
console.log("测试");
});
window.opener.postMessage("页面加载完成")
}
至此功能基本实现,剩下只有业务功能的完善。