iframe 子父传值封装 postmessage封装1.0
近期公司项目需求
1.父页面中同时载入多个iframe
2.父页面主动调用子页面方法
3.父页面主动获取子页面值
4子页面主动获取父页面的值
其中主动是关键
postmessage.js
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global = global || self, global.postmessage = factory())
}(this, function () {
const commonMethod = 'haha'
// 管道集合
const queueMap = new Map()
// 全局监听
window.addEventListener('message', function (event) {
const sourceUrl = event.data.sourceUrl
console.log('[addEventListener][event]', event)
console.log('我是' + location.href, '收到来自', sourceUrl + '的消息')
console.log('[当前管道集合]===', queueMap)
// 执行方法
queueMap.get(event.data.method + location.href).fn(event.data.data)
})
/**
* 给子页面传值
* @param {*} iframe
* @param {*} methodName
* @param {*} data
*/
function postToIframe (iframe, methodName, data, fn) {
// 目标iframe地址 通常指子页面地址
const iframeUrl = iframe.getAttribute('src') || iframe
console.log('我是:' + location.href, '我要给' + iframeUrl + '发消息', '消息标识:', methodName, '消息内容:', data)
iframe.contentWindow.postMessage({
method: methodName || commonMethod,
data: data,
sourceUrl: window.location.href
}, '*')
fn && listen(methodName, fn)
}
/**
* 给父级页面传值
* @param {*} methodName
* @param {*} data
*/
function postToParent (methodName, data, fn) {
window.parent.postMessage({
method: methodName || commonMethod,
data: data,
sourceUrl: window.location.href
}, '*')
fn && listen(methodName, fn)
}
function listen (methodName, fn) {
console.log('我是' + location.href, '注册' + methodName + '管道')
queueMap.set(methodName + location.href, { fn })
console.log('【当前订阅队列】', queueMap)
}
function trigger (iframe, methodName, data, fn) {
if (iframe) {
postToIframe(iframe, methodName, data, fn)
} else {
postToParent(methodName, data, fn)
}
}
return {
listen,
trigger
}
}))
parnet.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>parent</title>
</head>
<body>
<div id="app"></div>
<iframe id="childFrame" src="http://192.168.43.181:8080/child.html"></iframe>
<button onclick="checkForm1()">checkForm1</button>
<button onclick="getForm1()">getForm1</button>
<iframe id="childFrame2" src="http://192.168.43.181:8080/child2.html"></iframe>
<button onclick="checkForm2()">checkForm2</button>
<button onclick="getForm2()">getForm2</button>
<script src="./post-message.js"></script>
<script>
const personInfo = {
name: '666',
sex: '女'
}
postmessage.listen('getPersonInfo', function (data) {
const iframeDom = document.getElementById('childFrame')
postmessage.trigger(iframeDom, 'getPersonInfo', personInfo)
})
postmessage.listen('handleAlert', function (data) {
alert(data)
})
function checkForm1 () {
console.log('checkForm=====================')
const iframeDom = document.getElementById('childFrame')
postmessage.trigger(iframeDom, 'checkForm', { test: '请' + iframeDom.src + '校验表单:' }, function (result) {
console.log(iframeDom.src + '的表单校验结果:', result)
})
}
function getForm1 () {
console.log('getForm=======================')
const iframeDom = document.getElementById('childFrame')
postmessage.trigger(iframeDom, 'getForm', { test: '请给我表单' }, function (result) {
console.log(iframeDom.src + '的表单结果:', result)
})
}
function checkForm2 () {
console.log('checkForm2=====================')
const iframeDom = document.getElementById('childFrame2')
postmessage.trigger(iframeDom, 'checkForm', { test: '请' + iframeDom.src + '校验表单:' }, function (result) {
console.log(iframeDom.src + '的表单校验结果:', result)
})
}
function getForm2 () {
console.log('getForm2=======================')
const iframeDom = document.getElementById('childFrame2')
postmessage.trigger(iframeDom, 'getForm', { test: '请给我表单' }, function (result) {
console.log(iframeDom.src + '的表单结果:', result)
})
}
</script>
</body>
</html>
child.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>inner</title>
</head>
<body>
<div id="app">
<button onclick="getPersonInfo()">getPersonInfo</button>
<button onclick="handleAlert()">handleAlert</button>
</div>
<script src="./post-message.js"></script>
<script>
const form = {
result: 111,
aaa: 222,
bbb: 333
}
const getFormKey = 'getForm'
postmessage.listen(getFormKey, function (data) {
console.log('[child]getForm方法', '当前收件人' + location.href, '收到了消息', data)
postmessage.trigger(null, getFormKey, form)
})
const checkFormKey = 'checkForm'
postmessage.listen(checkFormKey, function (data) {
console.log('[child]checkForm方法', '当前收件人' + location.href, '收到了消息', data)
const checkResult = true
postmessage.trigger(null, checkFormKey, checkResult)
})
function getPersonInfo () {
console.log('child click getPersonInfo========>')
postmessage.trigger(null, 'getPersonInfo', 'test', function (result) {
console.log('我是' + location.href, '我拿到了从父级得到的数据Person', result)
})
}
function handleAlert () {
console.log('child click handleAlert========>')
postmessage.trigger(null, 'handleAlert', '我是child 传过去的值')
}
</script>
</body>
</html>
child2.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>inner</title>
</head>
<body>
<div id="app">
<button onclick="clickHandler()">post</button>
</div>
<script src="./post-message.js"></script>
<script>
const form = {
result: 'aaaaaaaaaaaaaaaaaa',
aaa: 'bbbbbbbbbbbbbbbbbbbbb',
bbb: '333'
}
postmessage.listen('getForm', function (data) {
console.log('getForm2收件人:', location.href, '收到了消息', data)
// setTimeout(function () {
postmessage.trigger(null, 'getForm', form)
// }, 2000)
}, location.href)
postmessage.listen('checkForm', function (data) {
console.log('checkForm2收件人:', location.href, '收到了消息', data)
const checkResult = false
// setTimeout(function () {
postmessage.trigger(null, 'checkForm', checkResult)
// }, 2000)
}, location.href)
</script>
</body>
</html>
简单解释一下,通过将回调方法写入执行map,通过key+href的方式实现精确调用特定方法
该版本为存在许多问题,以及使用上的限制,即将在接下来的2.0中引入id来解决目前存在的问题