vue中iframe使用以及结合postMessage实现跨域通信

目录
  • 使用场景
    • 需求
  • iframe使用
    • 基本使用
    • 常用属性
    • iframe高度自适应
    • 获取iframe的内容
    • 同域下获取父级/子级内容
    • iframe跨域
  • postMessage通信
    • 在vue中使用

使用场景

需求

在一个H5项目的页面中以url的方式嵌入另一个项目的页面。(不得不使用iframe)

而为了兼容移动端api(封装的一个移动端api,iframe内嵌页面不生效),需要实现父子页面的通信 (使用postMessage)。

iframe使用

基本使用

直接在页面嵌套iframe标签指定src即可使用iframe。

<iframe src="xxx.html"></iframe>

常用属性

  • frameborder:是否显示边框,1(yes),0(no)
  • height:框架作为一个普通元素的高度。
  • width:框架作为一个普通元素的宽度。
  • name:框架的名称,window.frames[name]时专用的属性。
  • scrolling:框架的是否滚动。yes,no,auto。
  • src:内框架的地址,可以使页面地址,也可以是图片的地址。
  • sandbox:对iframe进行一些列限制,IE10+支持

更多属性访问: 这里

iframe高度自适应

let ifr = document.getElementById('ifr')
const deviceHeight = document.documentElement.clientHeight;
ifr.style.height = (Number(deviceHeight)) + 'px'; 

vue中需要在mounted()中进行高度初始化

获取iframe的内容

通过两个主要的API:contentWindow 和 contentDocument

  • iframe.contentWindow,获取iframe的window对象
  • iframe.contentDocument,获取iframe的document对象
var iframe = document.getElementById("iframe1");
var iwindow = iframe.contentWindow;
var idoc = iwindow.document;
console.log("window",iwindow);    //获取iframe的window对象
console.log("document",idoc);    //获取iframe的document
console.log("html",idoc.documentElement);    //获取iframe的html
console.log("head",idoc.head);    //获取head
console.log("body",idoc.body);    //获取body

通过Name属性,通过window提供的frames获取

<iframe src ="xxx.html" id="ifr1" name="ifr1" scrolling="yes">
    <p>Your browser does not support iframes.</p>
</iframe>
<script type="text/javascript">
    console.log(window.frames['ifr1'].window);
    console.dir(document.getElementById("ifr1").contentWindow);
</script>

window.frames['ifr1'] 返回的就是window对象,即 window.frames['ifr1']===window

同域下获取父级/子级内容

  • window.parent:获取上一级的window对象,如果还是iframe则是该iframe的window对象
  • window.top:获取最顶级容器的window对象

iframe跨域

以下形式的跨域,可以使用iframe进行解决。某一方使用iframe嵌套在另一方。

比如:http://www.foo.com/a.html 和 http://script.foo.com/b.html

两个文件中分别加上 document.domain = 'foo.com',指定相同的主域,然后,两个文档就可以进行交互。

//b.html是以iframe的形式嵌套在a.html中
//www.foo.com上的a.html
document.domain = 'foo.com';
var ifr = document.createElement('iframe');
ifr.src = 'http://script.foo.com/b.html';
ifr.style.display = 'none';
document.body.appendChild(ifr);
ifr.onload = function(){
    var doc = ifr.contentDocument || ifr.contentWindow.document;
    // 在这里操纵b.html
    alert(doc.getElementsByTagName("h1")[0].childNodes[0].nodeValue);
};
//script.foo.com上的b.html
document.domain = 'foo.com';

默认情况下 document.domain 是指 window.location.hostname 。可以手动更改,但是最多只能设置为主域名。 通常,主域名就是指不带www的hostname, 比如: foo.com , baidu.com 。

如果,带上www或者其他的前缀,就是二级域名或者多级域名。通过上述设置,相同的domain之后,就可以进行同域的相关操作。

如果设置的iframe的域名和 top.window 的域名完全不同。则可以使用postMessage()进行通信

postMessage通信

window.postMessage() 方法可以安全地实现跨源通信。通常,对于两个不同页面的脚本,只有当执行它们的页面位于具有相同的协议(通常为https),端口号(443为https的默认值),以及主机 (两个页面的模数 Document.domain设置为相同的值) 时,这两个脚本才能相互通信。window.postMessage() 方法提供了一种受控机制来规避此限制,只要正确的使用,这种方法就很安全。

具体使用方式参考:window.postMessage

<iframe src="http://xxx.com" name="sendMessage"></iframe>

父页面向子页面传递信息:

// 父页面js
let ifr = window.frames['sendMessage'];
// 向子页面发送message
ifr.postmessage('give u a message', "http://xxx.com");
// xxx.com页面js
// 监听父页面传来的信息
window.addEventListener('message', receiver, false);
function receiver(e) {
    if (e.origin == 'http://xxx.com') {
        if (e.data == 'give u a message') {
            e.source.postMessage('received', e.origin);  // 向原网页返回信息
        } else {
            alert(e.data);
        }
    }
}

在vue中使用

<iframe :src="src" ref="iframe" frameborder="0"></iframe>

1.要将获取到iframe的contentWindow属性放到mounted这个钩子函数中。

mounted() {
    this.iframeWin = this.$refs.iframe.contentWindow;
}

2.子页面向父页面传值

父页面代码:

// 父页面监听子页面传来的信息
mounted() {
    window.addEventListener('message', this.handleMessage);
    this.iframeWin = this.$refs.iframe.contentWindow;
},
methods: {
    handleMessage (event) {
        const data = event.data.data
        if(data.info === "success"){
            alert(data.data)
        }
    }
}

子页面代码:

sendMessage() {
    // 向父页面发送信息
    window.parent.postMessage({
        data: {
            info:"success",
            data:"我是子页面的test!"
        }
    }, '*');
}

3.父页面向子页面传递信息同理

sendMessage () {
    // 向子页面传数据,需要注意这里没有parent
    this.iframeWin.postMessage({
        info: 'success',
        data: "我是来自父页面的data!"
    }, '*')
}

注意父向子传递信息的时候,要等子页面加载完成后,再进行通信

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • vue使用websocket概念及示例

    目录 概念部分: 使用示例 概念部分: 1,WebSocket 是 HTML5 提供的 TCP 连接上进行全双工通讯的协议.一次握手之后,服务器和客户端可以互相主动通信,双向传输数据. 2,浏览器想服务器发送请求,建立连接之后,可通过send()方法想服务器发送数据,并通过message事件接受服务器返回的数据. 使用示例 <script> export default { mounted() { this.connectWebsocket(); }, methods: { connectWe

  • postMessage及webSocket跨域方案详解

    目录 一.postMessage ✍是什么 ✍语法 ✍怎么用 ✍如何跨域 iframe + postMessage window.open()+postMessage ✍兼容性 二.webSocket ✍出现的原因 ✍连接流程 ✍兼容性 一.postMessage 我们在上一篇小白也能搞懂的JSONP和CORS跨域方案已经说过两种跨域方案了,这一篇就再继续讲讲postMessage和websocket这两种方案,它们也能算得上是跨域方案

  • 使用postMessage实现iframe跨域通信的示例代码

    1.父页面内容 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <h1>主页面</h1> <iframe id="child" src="http://10.0.0.159:8080"></i

  • 使用HTML5中postMessage知识点解决Ajax中POST跨域问题

    由于同源策略的限制,Javascript存在跨域通信的问题,典型的跨域问题有iframe与父级的通信等.常规的几种解决方法: (1) document.domain+iframe: (2) 动态创建script: (3) iframe+location.hash: (4) flash. postMessage是HTML5为解决js跨域问题而引入的新的API,允许多个iframe/window跨域通信. HTML5中提供了在网页文档之间相互接收与发送信息的功能.使用这个功能,只要获取到网页所在窗口

  • NodeJS落地WebSocket实践前端架构师破局技术

    目录 网络协议进化 Socket.IO? ws 模块实现 服务端 客户端 Express 集成 WebSocket 实例 浏览器 服务端 消息广播 安全与认证 Token 连接认证 wss 支持 BFF 应用 网络协议进化 HTTP 协议是前端最熟悉的网络通信协议.我们通常的打开网页,请求接口,都属于 HTTP 请求. HTTP 请求的特点是:请求-> 响应.客户端发起请求,服务端收到请求后进行响应,一次请求就完成了.也就是说,HTTP 请求必须由客户端发起,服务端才能被动响应. 除此之外,发起

  • react使用websocket实时通信方式

    目录 使用websocket实时通信 创建公共组件 在react组件中的使用 websocket在不同情形下的使用 1.在react中使用websocket 2.websocket在小程序中使用 使用websocket实时通信 在react中使用websocket不需要引入其他库,只需要创建一个公共组件,封装一下websocket 创建公共组件 websocket.js let websocket, lockReconnect = false; let createWebSocket = (ur

  • vue中iframe使用以及结合postMessage实现跨域通信

    目录 使用场景 需求 iframe使用 基本使用 常用属性 iframe高度自适应 获取iframe的内容 同域下获取父级/子级内容 iframe跨域 postMessage通信 在vue中使用 使用场景 需求 在一个H5项目的页面中以url的方式嵌入另一个项目的页面.(不得不使用iframe) 而为了兼容移动端api(封装的一个移动端api,iframe内嵌页面不生效),需要实现父子页面的通信 (使用postMessage). iframe使用 基本使用 直接在页面嵌套iframe标签指定sr

  • JavaScript使用HTML5的window.postMessage实现跨域通信例子

    JavaScript由于同源策略的限制,跨域通信一直是棘手的问题.当然解决方案也有很多: 1.document.domain+iframe的设置,应用于主域相同而子域不同: 2.利用iframe和location.hash,数据直接暴露在了url中,数据容量和类型都有限 3.Flash LocalConnection, 对象可在一个 SWF 文件中或多个 SWF 文件间进行通信, 只要 在同一客户端就行,跨应用程序, 可以跨域. window.name 保存数据以及跨域 iframe 静态代理动

  • Vue中iframe 结合 window.postMessage 实现跨域通信

    目录 一.前言 二.应用场景 2.1 嵌入页面 2.2 postMessage 实现父子页面通信 2.3 子页面向父页面传值 2.4父页面代码: 一.前言 什么是iframe? iframe 元素会创建包含另外一个文档的内联框架(即行内框架). 什么是postMessage? window.postMessage() 方法可以安全地实现跨源通信.通常,对于两个不同页面的脚本,只有当执行它们的页面位于具有相同协议(通常为https),端口号(443为https的默认值),以及主机 (两个页面的模数

  • Vue 使用postMessage 实现父子跨域通信

    目录 一.跨域通信 二.示例 三.拓展阅读 vue项目中postMessage的使用总结 postMessage简介 项目搭建 一.跨域通信 1.子向父通信parent.html // 页面销毁前,务必去除监听器,否则会造成资源泄露! beforeDestory () { window.removeEventListener('message', this.listenerFun) } mounted() { window.addEventListener('message',this.list

  • vue内嵌iframe跨域通信的实例代码

    目录 vue内嵌iframe跨域通信 1.Vue组件中如何引入iframe? 2.vue如何获取iframe对象以及iframe内的window对象? 3.vue如何向iframe内传送信息? 4.iframe内如何向外部vue发送信息? vue内嵌iframe跨域通信 1.Vue组件中如何引入iframe? <template> <div class="act-form"> <iframe :src="src"></ifr

  • 利用iframe实现ajax跨域通信的实现原理(图解)

    在漫长的前端开发旅途上,无可避免的会接触到ajax,而且一般情况下都是用在同一域下的ajax请求:但是如果请求是发生在不同的域下,请求就无法执行,并且会抛出异常提示不允许跨域请求,目前我没有找到明确的资料说明这是为什么,我觉得应该是出于安全性的考虑吧.纵然如此,要实现跨域访问的话,方法还是有的,而且不只一种,在这里介绍其中一种解决方案:如何利用iframe完成ajax的跨域请求. 如下图所示:域a.com的页面request.html(即http://a.com/request.html)里面嵌

  • iframe跨域通信封装详解

    iframe跨域通信 查看演示        源码下载 众所周知,由于前端javascript对跨域访问做了安全限制,javascript只能访问与包含它的文档在同一域下的内容. 用法举例: 需求是在http://www.demo.org/top.html中通过iframe方式嵌入http://www.iframe.com/iframe.html,而在iframe页面中希望通过点击一个按钮,调用top页面的一个js方法. 1. 在top页面中建立方法供内部页面使用 复制代码 代码如下: func

  • vue+springboot前后端分离实现单点登录跨域问题解决方法

    最近在做一个后台管理系统,前端是用时下火热的vue.js,后台是基于springboot的.因为后台系统没有登录功能,但是公司要求统一登录,登录认证统一使用.net项目组的认证系统.那就意味着做单点登录咯,至于不知道什么是单点登录的同学,建议去找一下万能的度娘. 刚接到这个需求的时候,老夫心里便不屑的认为:区区登录何足挂齿,但是,开发的过程狠狠的打了我一巴掌(火辣辣的一巴掌)...,所以这次必须得好好记录一下这次教训,以免以后再踩这样的坑. 我面临的第一个问题是跨域,浏览器控制台直接报CORS,

  • Vue项目前后端联调(使用proxyTable实现跨域方式)

    vue本地项目调试线上接口出现跨域问题 使用方法:vue在配置文件中提供了proxyTable来设置跨域,在config文件夹的index.js文件中 dev: { //开发环境下 // 静态资源文件夹 assetsSubDirectory: 'static', // 发布路径 assetsPublicPath: '/', // 代理配置表,在这里可以配置特定的请求代理到对应的API接口 // 例如将'localhost:8080/api/xxx'代理到'http://xxxxxxx.com/x

随机推荐