网页嵌入其他网站或新打开其他网页并发送消息

一、背景

公司A想开发一个包含功能1、2、3…的网站,经过调研发现,公司B开发的网站包含了其所需的一半功能,公司A想直接把公司B的网站嵌入到他们的网站中或通过一个按钮跳转到公司B的网站,并希望对公司B的网站做一些控制。

二、相关技术

2.1 网页嵌入

html提供了iframe标签用于在网页中嵌入其他网站,下面介绍几个主要的属性

2.1.1 src

用于设置嵌入网站的地址,如https://www.csdn.net,简单的使用如下,效果如下图

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
</head>
<body>
    <h2>嵌入CSDN</h2>
    <br>
    <iframe id="child" src='https://www.csdn.net'></iframe>
    <script>
    </script>
</body>
</html>

初始

2.1.2 width和height

width用于设置嵌入网页的宽度,height为高度。从上图可以看出默认的范围比较小,想要嵌入的网页范围变大,可设置这两个参数,单位为像素。如将上述的iframe参数改为如下,可得到较大范围的嵌入网页

<iframe id="child" src='https://www.csdn.net' width="1600px" height="800px"></iframe>

2.1.3 frameborder

用于控制嵌入的网页是否有边框,1为有边框,0为无边框。从上图中可以看出默认是带边框的。下图为无边框的效果。
no-border

2.1.4 scrolling

用于控制嵌入的网页是否有滑动条,1为有,0为无,默认为有。

2.2 打开新网页

作用 在新的网页中打开网站
语法 window.open(URL)

  1. URL为打开的页面的网址。如果没有指定网址,则打开一个新的空白窗口
  2. 返回新网页的window对象

2.3 网页通信

2.3.1 postMessage

作用 向其他窗口发送消息
语法 otherWindow.postMessage(message, targetOrigin, [transfer])

  1. otherWindow为其他窗口的一个引用,比如 iframecontentWindow 属性
  2. message为将要发送到其他 window的数据,为字符串
  3. targetOrigin为能接收到消息事件的窗口,格式为窗口的网址,如果想要所有窗口都能接收到消息,可设置为*
  4. [transfer]为可选参数,是一串和 message 同时传递的 Transferable 对象。这些对象的所有权将被转移给消息的接收方,而发送一方将不再保有所有权。此参数一般不使用

2.3.2 addEventListener

作用 接收消息
语法 window.addEventListener(event, function, useCapture)

  1. event为事件名称,一般为"message"
  2. function为消息处理函数,用户可自定义,输入参数为ee包含2个常用的参数,e.data为接收到的字符串消息;e.origin为发送消息的网址,可通过此参数来做判断是否需要处理,以防攻击
  3. useCapture用来处理当存在多级组件都有接收消息响应函数时的处理顺序,true表示从外向内,即外层的先响应,false为从内向外,默认为false

2.3.3 window.opener

window.opener为打开当前网页的网页对象,如winA.open(winB),则winB.openerwinA,使用该变量可实现被打开网页向主网页发送消息

2.4 使用window.onload来处理打开新窗口后异步执行的问题

  1. window.onload是一个在网页加载完成后自动执行的函数,用户可自定义该函数。
  2. 打开新窗口发送消息存在的问题:在向新窗口发送消息的案例中,由于window.open()需要时间,这个时间跟被打开的网站的加载速度有关,而该函数的执行是异步的,即该语句后面的代码不会等待新窗口完全加载后再执行,从而导致post的消息不起作用。
  3. 解决方法1:对window.open()后的代码使用setTimeout函数延迟执行,此方案严重依赖于设置的延迟时长,如果设置小了,代码执行不起作用;设置大了又会有明显的迟滞,且不同网站的加载速度不同,即便相同的网站,受限于网速,打开的速度也不一样,延迟时长很难设置。所以此方法不推荐。
  4. 解决方法2:在子页面的window中增加onload函数,在这个函数中我们使用window.opener来向主网页发送消息,告诉它子网页加载好了,然后主网页再发送消息给子网页进行处理,这样虽然会多一些交互代码,但可以精确地执行交互。所以推荐使用该方法,下述的案例中就使用了该方法。

三、代码案例

正常一般为网站服务,此处为了方便直接使用了html文件,其中postMessagetargetOrigin就无法设置html路径了,如果是服务的话可直接填网址,如"https://www.csdn.net",所以此处直接用"*"

3.1 主页面代码

<!-- main: child.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
</head>
<body>
    <h2>这是主网页</h2>
    <br>
    <span>向内嵌网页发送的消息</span>
    <input id="postMsg" type="text" value=""/>
    <button onclick="handleSendMsgToCurWindow()">发送到内嵌网页</button>
    <button onclick="handleSendMsgToNewWindow()">发送到新网页</button>
    <iframe id="child" src='child.html' frameborder="1" scrolling="yes" style="position:fixed; top: 150px; left: 10px; width:400px; height:200px"></iframe>
    <script>

        var newWindow = undefined; //子网页window

        function handleSendMsgToCurWindow(){           
            let postMsg = document.getElementById("postMsg").value;
            if(postMsg == ""){
                alert("消息不能为空!");
                return;
            }

            // 获取内嵌网页frame
            var childFrame = document.getElementById('child');
            childFrame.contentWindow.postMessage(postMsg, '*');
        }

        function handleSendMsgToNewWindow(){           
            let postMsg = document.getElementById("postMsg").value;
            if(postMsg == ""){
                alert("消息不能为空!");
                return;
            }

            if(newWindow == undefined){
                // 如果子网页未打开,则打开
                newWindow = window.open("child.html");

                // 子网页打开需要时间且是异步的,需要监听子网页是否完成加载的反馈,等加载完后再发送消息
                window.addEventListener('message', (e)=>{   
                    if(e.data == "childLoaded" && newWindow){
                        let postMsg = document.getElementById("postMsg").value;
                        newWindow.postMessage(postMsg, '*');
                    }
                    
                }, false)
            }else{
                // 如果子网页已经打开,则直接发送消息
                newWindow.postMessage(postMsg, '*');
            }
        }

    </script>
</body>
</html>

3.2 子页面代码

<!-- file: child.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
</head>
<body>
    <h2>这是内嵌网页</h2>
    <br>
    <span>从主网页收到的消息</span>
    <input id="recvMsg" type="text" value=""/>
    <script>

        window.addEventListener('message', (e)=>{
            console.log(e);
            document.getElementById("recvMsg").value = e.data;
        }, false)

        // 网页加载完后向父窗口发送加载完成的消息
        window.onload = ()=>{
            if(window.opener){
                window.opener.postMessage("childLoaded", "*");
            }
        }

    </script>
</body>
</html>

3.2 向内嵌网页发送消息效果展示

cur

3.3 向新打开的网页发送消息效果展示

new

  • 5
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小何又沐风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值