(一)主页面
1.解决跨域通信
2.解决iframe每次url改变都能及时显示不产生缓存导致空白页(请详细查看 forceUpdataIframe() 里的代码)
3.解决iframe的onload每次url改变都能触发(请详细查看 watch()、mounted() 里的代码)
4.解决子页面获取token后未能及时刷新自动登录问题(请详细查看 iframe.onload()、 sendToken() 里的代码)
5.解决准确友好的子页面加载状态提示(请详细查看 iframeInit() 里的代码)
<template>
<div id="iframeBox">
<iframe ref="iframe" name="refresh_name" class="iframe-style" frameborder="no" border="0" />
</div>
</template>
<script>
import { getToken, setToken } from "@/utils/auth";
export default {
name: "Iframe",
props: {
url: {
type: String,
default: "" // 先用hsa的这个页面
}
},
data() {
return {
loading: null,
myInterVal: null
};
},
watch: {
url(newVal, oldVal) {
if (getToken()) {
// console.log(JSON.stringify(getToken()), "后台管理系统的的getToken");
this.iframeInit(newVal);
}
}
},
created() {},
mounted() {
this.iframeInit(
""
// 默认打开为空白页
// https://xxx.xxxxx.com/hsa-local-test/web/uscCenterLocal/#/MenuManage
);
},
methods: {
sendToken(newVal) {
// // debugger;
const iframe = this.$refs.iframe;
//发送消息
iframe.contentWindow.postMessage(JSON.stringify(getToken()), "*");
//触发刷新
iframe.src = newVal;
//关闭加载
this.loading.close();
},
//iframe 初始化
iframeInit(newVal) {
//链接为空不显示加载状态和绑定ifram监听事件
if (newVal == "") {
return;
}
// debugger;
if (this.loading) {
this.loading.close();
}
this.loading = this.$loading({
target: "#iframeBox",
lock: true,
customClass: "global-loading",
text: "页面加载中...",
spinner: "el-icon-loading",
background: "transparent"
});
let iframe = this.$refs.iframe;
// 处理兼容行问题
if (iframe.attachEvent) {
iframe.attachEvent("onload", () => {
// debugger;
this.sendToken(newVal);
});
} else {
iframe.onload = () => {
// debugger;
console.log("isOnLoad");
this.sendToken(newVal);
};
}
// 接受子级返回数据
window.addEventListener(
"message",
function(e) {
// console.log("父级接收子级返回数据" + e.data);
if (typeof e.data === "string") {
setToken(JSON.parse(e.data));
}
},
false
);
//利用异步延迟加载和链接随机传参来达到刷新iframe缓存的目的,不加此步骤iframe页面不更新
this.forceUpdataIframe(iframe, newVal);
// debugger;
},
//强制刷新iframe缓存
forceUpdataIframe(iframe, newVal) {
setTimeout(() => {
let fresh_link =
new Date().getTime() + Math.floor(Math.random() * 1000000); //获取当前时间戳
String.prototype.splice = function(start, newStr) {
return this.slice(0, start) + newStr + this.slice(start);
};
let strIndex = newVal.indexOf("/#/");
let url = newVal.splice(strIndex, "?time=" + fresh_link);
console.log("url", url);
iframe.src = url;
// window.open(newVal + "?time=" + fresh_link, "refresh_name");
}, 300);
}
}
};
</script>
<style scoped>
.iframe-style {
/*100 = 顶部菜单+标签栏 */
min-height: calc(100vh - 85px);
width: 100%;
position: relative;
overflow: hidden;
box-shadow: 1px 1px 1px #eee;
/* margin: 16px 0 0 16px; */
}
</style>
(二)子页面
1.接收父级 token 并存储 token
newPromise.js
import {
setToken, getToken
} from '@/utils/auth'
const promise = function () {
return new Promise(async (resolve, reject) => {
if (!getToken()) {
window.addEventListener('message', function (e) {
if ((typeof e.data) === 'string') {
setToken(JSON.parse(e.data));
resolve(true)
}
// resolve(true) //说明 本地联调的时候开启 发布的时候要去掉
})
} else {
resolve(true)
}
})
}
export default promise
2.token过期时调用后端接口刷新 token ,并向父级发送 token 更新信息,让父级保存新token
request.js
import axios from 'axios'
import {
setToken, getToken
} from '@/utils/auth'
const service = axios.create({
...
})
// request interceptor
service.interceptors.request.use(config => {
...
})
// response interceptor
service.interceptors.response.use(
response => {
const res = response.data
if (res.code === 600003) {
refresh({ refreshToken: JSON.parse(getToken()).refreshToken || '' }).then(res => {
debugger
if (res.code === 0) {
let token = {
'accessToken': data.accessToken,
'refreshToken': data.refreshToken
}
setToken(token)//保存账户actoken和refreshToken
window.parent.postMessage(JSON.stringify(getToken()), '*')//子页面向父页面发送消息
setTimeout(() => {
window.location.reload()
}, 1200)
}
})
}
return res
}
)
3.挂载实例前调用接收消息
main.js
import promise from './newPromise.js'
// 挂载实例前调用接收消息
promise().then(() => {
new Vue({
el: '#app',
router,
store,
render: h => h(App)
})
})
(三)另附:auth.js
token工具类函数封装
import Cookies from 'js-cookie'
const TokenKey = 'my_token' // 需要存储token的 Cookies 前缀名称
export function getToken() {
return Cookies.get(TokenKey)
}
export function setToken(token) {
return Cookies.set(TokenKey, token)
}
export function removeToken() {
return Cookies.remove(TokenKey)
}
网友评论