iframe 详解-在vue中使用iframe/iframe在vue中使用 - TheYouth - 博客园

一、什么是iframe?

  1. 使用 iframe + postMessage 实现跨域通信

     MDN: https://developer.mozilla.org/zh-CN/docs/Web/API/Window/postMessage[
](https://developer.mozilla.org/zh-CN/docs/Web/API/Window/postMessage "MDN")

  在实际项目开发中可能会碰到在 aa.com 页面中嵌套 bb.com 页面,这时第一反应是使用 iframe,但是产品又提出在 aa.com 中操作,bb.com 中进行显示,或者相反。

      postMessage语法:

?

1

2

3

4

5

6

otherWindow.postMessage(message, targetOrigin, [transfer]);

otherWindow:其他窗口的一个引用(在这里我使用了iframe的contentWindow属性)

message:将要发送到其他window的数据

targetOrigin:通过窗口的origin属性来指定哪些窗口能接收到消息事件,其值可以是字符串`"*"`(表示无限制)或者一个URI。在发送消息的时候,如果目标窗口的协议、主机地址或端口这三者的任意一项<br>不匹配targetOrigin提供的值,那么消息就不会被发送;只有三者完全匹配,消息才会被发送。这个机制用来控制消息可以发送到哪些窗口;例如,当用postMessage传送密码时,这个参数就显得尤为重要,<br>必须保证它的值与这条包含密码的信息的预期接受者的origin属性完全一致,来防止密码被恶意的第三方截获。如果你明确的知道消息应该发送到哪个窗口,那么请始终提供一个有确切值的targetOrigin,而不是*。<br>不提供确切的目标将导致数据泄露到任何对数据感兴趣的恶意站点。

transfer:可选参数

二、遇到的问题

  1. postMessage发送消息跨域问题

?

1

2

// 不限制域名就用*,否则就是具体域名,这样可以解决跨域问题

iframe.postMessage(dict, '*'`)`

  2. postMessage传递数据的格式

?

1

2

3

4

5

6

7

8

9

10

data: {`// 最外面这个是postMeaage自带的,下面才是自己定义的数据格式,也可以不要内层的data:`

data: {

responseCode: '000000'

body: {

id: ""

name: "模板1"

}

}

type: "TYPE"

}

三、实例代码如下:下面的是iframe实用的例子,应用的是postMessage发送的消息,本例是父组件往子组件传递数据

注意:如果使用postMessage发送消息时,如果不使用按钮触发的话,有可能发送失败,所以下面例子针对此情景做了发送消息失败的处理方案

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

<template>

<div class`="main-info">`

<iframe

ref=`"iframe"`

id=`"iframe"`

frameborder=`"0"`

:src=`"iframeSrc"`

style=`"min-height: 800px;width: 100%"`

>

</iframe>

</div>

</template>

// 定义数据

data () {

return {

iframeSrc: ''`,`

iframe: ''`,`

isReceiveMsg: false`, // 是否收到消息,收到消息停止计时器,不再发送postMessage消息`

actionNum: 5, // 最多执行5次

timer: null`,`// 定时器

}

},

created() {

this`.iframeSrc = http:``//www.baidu.com`

// 监听收到消息

window.addEventListener(`'message',` `this.handleMessageEvent)`

},

mounted () {

const self = this

this`.$nextTick(() => {`

const iframe = document.getElementById(`'iframe'`)

if (iframe.attachEvent) { // 适配IE

iframe.attachEvent(`'onload'`, function () {

self.clickIframe()

setTimeout(() => {

self.handlePostMessageFail()

}, 1000)

})

} else {

iframe.onload = function () {

// 坑一,postMessage发送通知时,可能对方的页面还没有加载完成导致发送失败

self.clickIframe()

setTimeout(() => {

self.handlePostMessageFail()

}, 1000) } } })

}

},

methods: {

handleMessageEvent(event) {

if (event.data && event.data.data) {

const data = event.data.data

const body = data.body || ''

if (parseInt(data.responseCode) === 0) {

// 成功返回

setTimeout(() => {

this`.$router.push({ name: this`.backPath })

}, 500)

} else if (parseInt(data.responseCode) === 2) {

// 收到消息

console.log(`'-------已收到消息'`, data)

this`.isReceiveMsg = true`

}

}

},

clickIframe() {

const iframe =

document.getElementById(`'iframe'`) &&

document.getElementById(`'iframe'`).contentWindow

if (!iframe) return

const list = []

list.push(`this`.processData)

const dict = {

processList: list

}

// 不限制域名就用*,否则就是具体域名

iframe.postMessage(dict, '*'`)`

},

// 其中clickIframe里是处理iframe的src的

// 处理失败机制

// postMessage消息发送失败机制,上面定义执行5次,第隔1.5秒,之前设置3次,间隔一秒,还是有失败的,所以这里采用这个

handlePostMessageFail () {

this`.timer = setInterval(() => {`

if (!`this`.isReceiveMsg) {

if (`this`.actionNum <= 0) {

clearInterval(`this`.timer)

this`.timer = null`

this`.isReceiveMsg = true`

return

}

this`.clickIframe()`

this`.actionNum--`

} else {

clearInterval(`this`.timer)

this`.timer = null`

this`.isReceiveMsg = true`

}

}, 1500)

},

// 记得离开页面时,要消毁掉

destroyed() {

window.removeEventListener(`'message',` `this.handleMessageEvent)`

}


原网址: 访问
创建于: 2023-08-08 09:50:16
目录: default
标签: 无

请先后发表评论
  • 最新评论
  • 总共0条评论