Test.js 在iframe内的html页面引入
// 在iframe子页面引入该js
window.addEventListener ('message', function(event) {
/**
* 可以在这个地方调用HTML
*/
console.log('调用HTML')
if (event&&event.data){
console.log(event.data)
console.log('开始执行调用HTML')
//ifream加载完成时调用vue中的load方法,将父组件的所有方法告诉ifream中的页面
event.data.parentFunctions&&event.data.parentFunctions.forEach(key=>{
this.__proto__[key]=function (params) {
//调用父类
window.parent.postMessage ({functionName:key,params:params}, '*');
}
})
//vue页面传入数据如果是调用html方法 则使用此方法
event.data.functionName&&this[event.data.functionName](event.data.params)
}
});
child2.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="Test.js"></script>
<script>
function lodaTable(data) {
this.skipHtml({name:'test01',functionName:'changge',params:{personName:'张三'}})
console.log('name---->'+data)
}
</script>
</head>
<body>
<button onclick="lodaTable()">打开下一页</button>
<h1>首页</h1>
</body>
</html>
404.html 页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>404</h1>
</body>
</html>
Home.vue
<template>
<div class="iframestyleset">
<button @click="invokeHtmlMethod({
name:'test01',
url:'static/test01.html'
})">调用html方法
</button>
<a href="https://www.baidu.com/">打开百度</a>
<button @click="goBack()">回退</button>
<iframe style="background-color: #42b983" v-for="(item,index) in cachePath " name="iframeMap" :id="item.name"
:src="item.url" width="100%" height="200px" @load="load(item)" frameborder="0" scrolling="no"
ref="iframeDom"></iframe>
</div>
</template>
<script>
export default {
data() {
return {
getPageUrl: 'static/child2.html',
currentPages: [{
name: 'test01',
url: 'static/test01.html'
}, {
name: 'test02',
url: 'static/test02.html'
}, {
name: 'test03',
url: 'static/test03.html'
}],
cachePath: [{
name: 'child2',
url: 'static/child2.html'
}]
}
},
created() {
// 绑定监听,主要是为了接收html页面发来的消息
window.addEventListener('message', event => {
console.log('html子页面传来的数据')
console.log(event)
//执行子页面想要调用的方法
if (event && event.data) {
event.data.functionName && this[event.data.functionName](event.data.params)
}
})
},
mounted() {
let jz = this.cachePath.findIndex(item => item.name == 'child3')
console.log('jz===>' + jz)
},
methods: {
skip(page={name:undefined,functionName:undefined,params:undefined,type:undefined}) {
if (page.type === 'html' || page.type == '1') {
this.skipHtml(page)
} else if (page.type === 'vue' || page.type == '2') {
this.skipVue(page)
} else {
throw Error('page type no null (缺少type参数 vue | html | 1 | 2)')
}
},
/**
* vue 跳转
* {name:vue名称,params:要传入的数据}
*/
skipVue(page={name:undefined,params:undefined}) {
// {name: "deepReadingDetail", params: {'id': data.id, 'title': data.title}}
console.log('跳转Vue:' + page)
this.$router.push(page)
},
/**
* html 跳转
* {name:html名称,functionName:要调用的函数名称,params:要调用的函数要传入的数据}
*/
skipHtml(page={name:undefined,functionName:undefined,params:undefined}) {
console.log('跳转html:' + JSON.stringify(page))
alert('跳转html:' + JSON.stringify(page))
//1.首先判断这个地址是否存在
let currentPage = this.currentPages.find(item => item.name == page.name)
if (currentPage) {
//2.判断是否已经加载过
let jz = this.cachePath.findIndex(item => item.name == page.name)
Object.assign(page, currentPage)//合并对象
alert('page--->' + JSON.stringify(page))
if (jz > -1) {
//已经记载 则置顶
alert('已经记载 则置顶'+jz)
if (!(jz>=this.cachePath.length-1)){
alert(5555555)
this.cachePath.push(this.cachePath.splice(jz, 1)[0])
}
this.load(page)
} else {
alert('没有加载过 则添加')
//没有加载过 则添加
this.cachePath.push(page)
}
} else {
if (this.cachePath[this.cachePath.length-1].name!='404'){
this.cachePath.push({name: '404',url: 'static/404.html'})
}
}
},
invokeHtmlMethod(page) {
let frame = document.getElementById(page.name)
frame.contentWindow.postMessage(page, '*');
},
load(page) {
this.$nextTick(() => {
//1.获取到iframe对象
let frame = document.getElementById(page.name)
//2.给对象的contentWindow添加监听事件 parentFunctions(当前vue页面中的方法不要以$和_开头)
let parentFunctions = Object.keys(this).filter(key => {
if (!key.startsWith('$') && !key.startsWith('_') && typeof this[key] === 'function') {
return key
}
})
//3.告诉html页面 上个页面 要对他进行的操作 {parentFunctions:当前vue页面中的方法集合(必传),
// functionName:要调用的html中的方法(可空),
// params:要调用的html中的方法所传的参数(可空)
// }
//在将要进入的页面 可以直接使用this.方法名(参数)使用当前vue页面中的所有方法
frame.contentWindow.postMessage(Object.assign({parentFunctions: parentFunctions},page), '*');
})
},
goBack() {
if (this.cachePath.length>1){
this.cachePath.pop()
}
}
}
}
</script>
Vue目录结构