一、刷新iframe页面
iframe的地址没有改变的话,每打开一次iframe页面,都不会主动更新页面的。
以下有几种方法,都可以实现,每打开一次页面,就刷新一下
给iframe添加key
<template>
<div id="Iframe">
<el-dialog
append-to-body
style="margin-top: -10vh"
custom-class="scrollbar"
:visible.sync="iframeVisible"
width="90%"
@close="close"
>
<iframe
:key="key"
id="iframe"
ref="iframeBox"
:src="url"
frameborder="0"
width="100%"
sandbox="allow-forms allow-scripts allow-same-origin allow-popups"
:style="{ height: calHeight }"
scrolling="auto"
></iframe>
</el-dialog>
</div>
</template>
<script>
import { mapGetters } from "vuex";
import { getToken, setToken } from "@/utils/auth";
export default {
name: "Iframe",
computed: {
...mapGetters(["userid", "name"]),
//计算属性 , 设置iframe高度为窗口高度少100px
calHeight() {
return window.innerHeight - 150 + "px";
},
},
props: {
url: String,
dataid: String,
},
data() {
return {
iframeVisible: false,
key: new Date().getTime(),
};
},
watch: {
// 方法一:
// iframe上添加key,然后监听
$route: {
handler(val) {
this.key = new Date().getTime();
},
immediate: true,
},
},
};
</script>
给iframe的src中的地址添加时间戳
<template>
<div id="Iframe">
<el-dialog
append-to-body
style="margin-top: -10vh"
custom-class="scrollbar"
:visible.sync="iframeVisible"
width="90%"
@close="close"
>
<iframe
id="iframe"
ref="iframeBox"
:src="url"
frameborder="0"
width="100%"
sandbox="allow-forms allow-scripts allow-same-origin allow-popups"
:style="{ height: calHeight }"
scrolling="auto"
></iframe>
</el-dialog>
</div>
</template>
<script>
import { mapGetters } from "vuex";
import { getToken, setToken } from "@/utils/auth";
export default {
name: "Iframe",
computed: {
...mapGetters(["userid", "name"]),
//计算属性 , 设置iframe高度为窗口高度少100px
calHeight() {
return window.innerHeight - 150 + "px";
},
},
props: {
url: String,
dataid: String,
},
data() {
return {
iframeVisible: false,
};
},
watch: {
url(newVal, oldVal) {
if (getToken()) {
// 方法二
this.iframeInit(newVal);
}
},
},
methods: {
//iframe 初始化
iframeInit(newVal) {
let iframe = document.createElement("iframe");
//利用异步延迟加载和链接随机传参来达到刷新iframe缓存的目的,不加此步骤iframe页面不更新
this.forceUpdataIframe(iframe, newVal);
},
//强制刷新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>
二、iframe已经加载完毕,但是进度条还一直加载中
其他软件会影响iframe
我遇到的情况是,我这边没有任何问题,其他人也没有,但是又一个人就是遇到进度条一直在加载中,后来发现是因为他电脑上的小狐狸钱包在后台运行,所以影响到了iframe,把它关掉就可以了。
三、iframe传参
我这里是点击按钮,出现iframe页面,iframe是封装在弹窗中的,你们用的话直接在页面中使用iframe,然后跳转就行,就不一定要封装iframe了。
这里我就把主要代码贴出来
1、获取iframe的src中的参数
使用页面传递参数
<template>
<div id="EditDialog">
<el-dialog
append-to-body
custom-class="dialog"
:title="title.appname"
:visible.sync="dialog"
width="90%"
style="margin-top: -10vh"
>
<div
style="display: inline; margin: 0 5px"
v-for="(obj, ind) in List.button"
:key="ind"
>
<el-button
v-if="obj.type === 3"
size="small"
class="Cancelbtn"
@click="newpage(obj)"
>{{ obj.name }}</el-button
>
</div>
</el-dialog>
<!-- 新页面 -->
<Iframe ref="Iframe" :dataid="Form.dataid" :url="url"></Iframe>
</div>
</template>
<script>
import { mapGetters } from "vuex";
import Iframe from "@/views/dashboard/Iframe/Iframe.vue";
import { AddComments, Reject,Confirm,BpmUrge,BpmBack,BPMALL} from "@/api/Bpm";
export default {
data() {
return {
dialog: false,
url: "", //给iframe的地址
};
},
methods: {
//打开iframe页面
newpage(obj) {
// obj.add_url后端返回的是这样的:http://192.168.4.160:9528/#/Generation?dataid={dataid}
//其中http://192.168.4.160:9528是在开发阶段就是我们前端运行的地址,项目部署后,就是后端正式的地址
// /#/Generation是页面
//dataid是参数,需要我们赋值的
if (obj.add_url) {
const a = obj.add_url.replace(/{dataid}/, this.Form.dataid);
obj.add_url = a; //绝对路径,也就是http://192.168.4.160:9528开头
this.url = a;
//注意使用这种方法iframe需要加sandbox="allow-forms allow-scripts allow-same-origin allow-popups",不然会全屏
//this.List.add_url = `/#/Generation`;//相对路径
}
this.$refs.Iframe.iframeVisible = true;//打开组件的弹窗
},
}
}
</script>
iframe组件
<template>
<div id="Iframe">
<el-dialog
append-to-body
style="margin-top: -10vh"
custom-class="scrollbar"
:visible.sync="iframeVisible"
width="90%"
@close="close"
>
<iframe
:key="key"
id="iframe"
ref="iframeBox"
:src="url"
frameborder="0"
width="100%"
sandbox="allow-forms allow-scripts allow-same-origin allow-popups"
:style="{ height: calHeight }"
scrolling="auto"
></iframe>
</el-dialog>
</div>
</template>
<script>
import { mapGetters } from "vuex";
import { getToken, setToken } from "@/utils/auth";
export default {
name: "Iframe",
computed: {
...mapGetters(["userid", "name"]),
//计算属性 , 设置iframe高度为窗口高度少100px
calHeight() {
return window.innerHeight - 150 + "px";
},
},
props: {
url: String,
dataid: String,
},
data() {
return {
iframeVisible: false,
key: new Date().getTime(),
};
},
watch: {
$route: {
handler(val) {
this.key = new Date().getTime();
},
immediate: true,
},
},
mounted() {
// 注册监听框架传来的数据
this.$nextTick(() => {
// 在外部 Vue 的 window 上添加 postMessage 的监听,并且绑定处理函数 handleMessage
window.addEventListener("message", this.handleMessage);
});
},
destroyed() {
// 注意移除监听!
window.removeEventListener("message", this.handleMessage);
},
methods: {
close() {
this.iframeVisible = false;
},
handleMessage(event) {
if (event) {
this.iframeVisible = event.data;
} else {
this.iframeVisible = true;
}
},
},
};
</script>
<style lang="scss">
#Iframe {
width: 100%;
// height: 100%;
// padding: 0 10vw;
z-index: -1 !important;
.el-dialog__header {
background-color: transparent !important;
padding: 0;
}
.el-dialog__body {
background-color: #f9fafc;
border-radius: 10px;
padding: 40px 50px 30px;
height: calc(100vh - 80px);
overflow: hidden;
overflow-y: scroll;
&::-webkit-scrollbar {
width: 6px;
height: 6px;
}
// 滚动条的轨道的两端按钮,允许通过点击微调小方块的位置。
&::-webkit-scrollbar-button {
display: none;
}
// 滚动条里面的小方块,能向上向下移动(或往左往右移动,取决于是垂直滚动条还是水平滚动条)
&::-webkit-scrollbar-thumb {
background: rgba(144, 147, 153, 0.3);
cursor: pointer;
border-radius: 4px;
}
// 边角,即两个滚动条的交汇处
&::-webkit-scrollbar-corner {
display: none;
}
// 两个滚动条的交汇处上用于通过拖动调整元素大小的小控件
&::-webkit-resizer {
display: none;
}
}
.el-dialog__headerbtn .el-dialog__close {
color: #909399;
width: 50px;
height: 30px;
line-height: 30px;
border-radius: 5px;
background-color: #fff;
box-shadow: 2px 2px 6px rgba(138, 169, 192, 0.2);
}
// 发起新的弹窗
.dialog-footer {
height: 50px;
line-height: 50px;
background: #fff;
box-shadow: 2px 2px 6px rgba(138, 169, 192, 0.2);
border-radius: 5px;
flex-wrap: wrap;
margin-top: 20px;
}
.dialog-header {
height: 60px;
line-height: 60px;
background: #fff;
box-shadow: 2px 2px 6px rgba(138, 169, 192, 0.2);
border-radius: 5px;
flex-wrap: wrap;
margin-bottom: 20px;
padding: 0 10px;
font-size: 16px;
font-weight: 600;
}
.center {
display: flex;
width: 100%;
background: #fff;
box-shadow: 2px 2px 6px rgba(138, 169, 192, 0.2);
border-radius: 5px;
padding: 20px;
}
}
.scrollbar {
width: 100%;
// height: 100%;
// padding: 0 10vw;
z-index: -1 !important;
.el-dialog__header {
background-color: transparent !important;
padding: 0;
}
.el-dialog__body {
background-color: #f9fafc;
border-radius: 10px;
padding: 40px 50px 30px;
height: calc(100vh - 80px);
overflow: hidden;
overflow-y: scroll;
&::-webkit-scrollbar {
width: 6px;
height: 6px;
}
// 滚动条的轨道的两端按钮,允许通过点击微调小方块的位置。
&::-webkit-scrollbar-button {
display: none;
}
// 滚动条里面的小方块,能向上向下移动(或往左往右移动,取决于是垂直滚动条还是水平滚动条)
&::-webkit-scrollbar-thumb {
background: rgba(144, 147, 153, 0.3);
cursor: pointer;
border-radius: 4px;
}
// 边角,即两个滚动条的交汇处
&::-webkit-scrollbar-corner {
display: none;
}
// 两个滚动条的交汇处上用于通过拖动调整元素大小的小控件
&::-webkit-resizer {
display: none;
}
}
.el-dialog__headerbtn .el-dialog__close {
color: #909399;
width: 50px;
height: 30px;
line-height: 30px;
border-radius: 5px;
background-color: #fff;
box-shadow: 2px 2px 6px rgba(138, 169, 192, 0.2);
}
// 发起新的弹窗
.dialog-footer {
height: 50px;
line-height: 50px;
background: #fff;
box-shadow: 2px 2px 6px rgba(138, 169, 192, 0.2);
border-radius: 5px;
flex-wrap: wrap;
margin-top: 20px;
}
.dialog-header {
height: 60px;
line-height: 60px;
background: #fff;
box-shadow: 2px 2px 6px rgba(138, 169, 192, 0.2);
border-radius: 5px;
flex-wrap: wrap;
margin-bottom: 20px;
padding: 0 10px;
font-size: 16px;
font-weight: 600;
}
.center {
display: flex;
width: 100%;
background: #fff;
box-shadow: 2px 2px 6px rgba(138, 169, 192, 0.2);
border-radius: 5px;
padding: 20px;
}
}
</style>
iframe要跳转到的页面,接收参数
data() {
return {
dataid: "", //编辑弹窗传递的参数
};
},
created() {
// 获取父级中iframe的src,这样就可以获取参数
this.dataid = window.parent.document
.getElementById("iframe")
.src.split("=")[1];
},
2、获取并修改父组件的数据
我这里是iframe是在弹窗中的,当我在iframe中的页面点击按钮后,需关闭iframe所在弹窗,也就是需要获取父组件的数据并修改
父组件(放置iframe的页面)
<template>
<div id="Iframe">
<el-dialog
append-to-body
style="margin-top: -10vh"
custom-class="scrollbar"
:visible.sync="iframeVisible"
width="90%"
@close="close"
>
<iframe
:key="key"
id="iframe"
ref="iframeBox"
:src="url"
frameborder="0"
width="100%"
sandbox="allow-forms allow-scripts allow-same-origin allow-popups"
:style="{ height: calHeight }"
scrolling="auto"
></iframe>
</el-dialog>
</div>
</template>
<script>
import { mapGetters } from "vuex";
export default {
name: "Iframe",
computed: {
...mapGetters(["userid", "name"]),
//计算属性 , 设置iframe高度为窗口高度少100px
calHeight() {
return window.innerHeight - 150 + "px";
},
},
props: {
url: String,
dataid: String,
},
data() {
return {
iframeVisible: false,
key: new Date().getTime(),
};
},
watch: {
// iframe上添加key,然后监听
$route: {
handler(val) {
this.key = new Date().getTime();
},
immediate: true,
},
},
mounted() {
// 注册监听框架传来的数据
this.$nextTick(() => {
// 在外部 Vue 的 window 上添加 postMessage 的监听,并且绑定处理函数 handleMessage
window.addEventListener("message", this.handleMessage);
});
},
destroyed() {
// 注意移除监听!
window.removeEventListener("message", this.handleMessage);
},
methods: {
close() {
this.iframeVisible = false;
},
handleMessage(event) {
if (event) {
this.iframeVisible = event.data;
} else {
this.iframeVisible = true;
}
},
},
};
</script>
子组件(iframe中跳转的页面)
<template>
<div id="GetFrom">
<el-button size="small" class="addbtn" @click="sub()">保存</el-button >
</div>
</template>
<script>
export default {
methods: {
sub() {
window.parent.postMessage(false, "*"); //关闭iframe所在的弹窗
},
},
};
</script>
3、父组件传递数据给子组件
父组件
<template>
<div id="Iframe">
<button @click="sendMessage()">向iframe通信</button>
<iframe
:key="key"
id="iframe"
ref="iframeBox"
:src="url"
frameborder="0"
width="100%"
sandbox="allow-forms allow-scripts allow-same-origin allow-popups"
:style="{ height: calHeight }"
scrolling="auto"
></iframe>
</div>
</template>
<script>
import { mapGetters } from "vuex";
export default {
name: "Iframe",
computed: {
...mapGetters(["userid", "name"]),
//计算属性 , 设置iframe高度为窗口高度少100px
calHeight() {
return window.innerHeight - 150 + "px";
},
},
props: {
url: String,
dataid: String,
},
data() {
return {
key: new Date().getTime(),
iframeWin:'',
};
},
watch: {
// iframe上添加key,然后监听
$route: {
handler(val) {
this.key = new Date().getTime();
},
immediate: true,
},
},
mounted() {
// 注册监听框架传来的数据
this.iframeWin = this.$refs.iframeBox.contentWindow
},
methods: {
sendMessage() {
// 外部vue向iframe内部传数据
const a = {
b: 'Hello-iframe',
};
//转化为json字符串,兼容低版本浏览器
const data = JSON.stringify(a)
this.iframeWin.postMessage(data, '*')
},
},
};
</script>
子组件
<script>
export default {
data() {
return {
iframeVisible: false,
key: new Date().getTime(),
};
},
mounted() {
// 注册监听,接受父页面消息
this.$nextTick(() => {
window.addEventListener("message", this.handleMessage);
});
},
destroyed() {
// 注意移除监听!
window.removeEventListener("message", this.handleMessage);
},
methods: {
handleMessage(event) {
// 接受消息
const x = event.data
const data = JSON.parse(x)
switch (data.b) {
case 'Hello-iframe':
{
console.log("来自父页面的消息");
break;
}
}
},
},
};
</script>
四、其他问题
1、iframe页面中需要使用wordexport等功能
给代码加上sandbox=“allow-downloads”
<iframe
:key="key"
id="iframe"
ref="iframeBox"
:src="url"
frameborder="0"
width="100%"
sandbox="allow-forms allow-scripts allow-same-origin allow-popups allow-downloads"
:style="{ height: calHeight }"
scrolling="auto"
></iframe>
补充sandbox
allow-forms:允许资源提交表单。如果不使用此关键字,则阻止表单提交。
allow-modals:允许资源打开模式窗口。
allow-orientation-lock:允许资源锁定屏幕方向。
allow-pointer-lock:允许资源使用Pointer Lock API。
allow-popups:允许弹出窗口(例如window.open(),target =“ _ blank”或showModalDialog())。如果不使用此关键字,则弹出窗口将以静默方式无法打开。
allow-popups-to-escape-sandbox:允许沙盒文档打开新窗口,而这些窗口不会继承沙盒。例如,这可以安全地将广告沙箱化,而不必对广告链接到的页面施加相同的限制。
allow-presentation:让资源开始演示会话。
allow-same-origin:如果不使用此令牌,则资源被视为来自特殊来源,该来源始终失败于同源政策。
allow-scripts:让资源运行脚本(但不创建弹出窗口)。
allow-storage-access-access:允许资源使用Storage Access API请求访问父级的存储功能。
allow-top-navigation:允许资源浏览顶级浏览上下文(一个名为_top的浏览上下文)。
allow-top-navigation:允许资源导航顶级浏览上下文,但仅在由用户手势启动的情况下。
2、iframe在弹窗中
需要给iframe添加sandbox,不然会默认全屏
sandbox="allow-forms allow-scripts allow-same-origin allow-popups"
3、iframe展示PDF不显示
iframe嵌套iframe,父组件iframe中使用了沙盒sandbox,从而子组件iframe显示不了PDF
我没有其他方法,就是把子组件iframe提取出来,放到弹窗中,不放在父组件里
4、iframe中不能使用this.$parent.方法名()的方法来获取父组件的方法
因为获取不准确,比如iframe是在弹窗中,我点击按钮后,想要把当前弹窗关闭,同时也关闭父组件弹窗,发现使用this.$parent.方法名()这个方法,获取到的是主页面的数据,并不是父组件弹窗的数据
还是使用window.parent.postMessage();的方法来进行关闭父组件的弹窗,这时可以使用传递数据的方法,来传递多个数据
父组件(放置iframe的页面)
<script>
methods: {
handleMessage(event) {
// console.log(event.data);
if (event) {
this.iframeVisible = event.data[0];
if (event.data.lenght > 1 && event.data[1] === "shownew") {
this.$parent.shownew(); //调用父组件editdialog中的方法,父组件的方法中就有相关操作
}
} else {
this.iframeVisible = true;
}
},
},
};
</script>
子组件(iframe中跳转的页面)
<template>
<div id="GetFrom">
<el-button size="small" class="addbtn" @click="sub()">保存</el-button >
</div>
</template>
<script>
export default {
methods: {
sub() {
window.parent.postMessage([false,'shownew'], "*"); //关闭iframe所在的弹窗
},
},
};
</script>
editdialog的方法
<script>
export default {
methods: {
// 关闭页面,并刷新主页面,这个主要是给iframe弹窗的下发用的
shownew() {
this.$parent.BpmGetList(this.$parent.form); //主页面刷新
this.dialogHead = false;
this.dialog = false; //当前弹窗关闭
},
},
};
</script>
5、获取父组件iframe的src路径地址,从而获取其中的参数
父级的src的格式: http://192.168.4.248:9528/#/Getput?dataid=5
created() {
// 获取父级中iframe的src,这样就可以获取参数
this.dataid = window.parent.document
.getElementById("iframe")
.src.split("=")[1];
},
这篇文章看完如果您觉得有所收获,认为还行的话,就点个赞收藏一下呗