-
Notifications
You must be signed in to change notification settings - Fork 27
/
Copy pathOneIframe.vue
107 lines (99 loc) · 2.46 KB
/
OneIframe.vue
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
103
104
105
106
107
<script>
import Vue from 'vue'
export default {
name: 'one-iframe',
props: {
globalStyle: String,
live: Boolean
},
watch: {
globalStyle (value) {
if (this.style) {
this.style.textContent = value
}
}
},
beforeDestroy () {
if (this.mo) {
this.mo.disconnect()
}
},
mounted () {
const links = document.querySelectorAll('link[rel=stylesheet]')
const styles = document.querySelectorAll('style')
const { head } = this.$el.contentDocument
;[...links, ...styles].forEach(node => {
const clone = node.cloneNode(true)
head.appendChild(clone)
})
if (this.globalStyle) {
const style = document.createElement('style')
style.textContent = this.globalStyle
head.appendChild(style)
this.style = style
}
this.renderContents()
if (this.live) {
this.watchLiveStyle(head)
}
},
beforeUpdate () {
this.app.contents = Object.freeze(this.$slots.default)
},
methods: {
renderContents () {
const contents = this.$slots.default
const body = this.$el.contentDocument.body
const el = document.createElement('div')
body.appendChild(el)
this.app = new Vue({
el,
data () {
return {
contents: Object.freeze(contents)
}
},
render (h) {
return h('div', this.contents)
}
})
},
watchLiveStyle (head) {
this.liveStyle = document.createComment('')
head.appendChild(this.liveStyle)
this.mo = new MutationObserver(mutations => {
for (const mutation of mutations) {
if (mutation.target === document.head) {
const style = (this.liveSource = [...mutation.addedNodes].find(
node => node.nodeName === 'STYLE' && node.dataset.cssscoper
))
if (style) {
const liveStyle = style.cloneNode(true)
head.replaceChild(liveStyle, this.liveStyle)
this.liveStyle = liveStyle
}
} else if (mutation.target === this.liveSource) {
this.liveStyle.textContent = this.liveSource.textContent
}
}
})
this.mo.observe(document.head, { childList: true })
}
},
render (h) {
return h('iframe', {
class: {
'one-iframe': true
}
})
}
}
</script>
<style lang="stylus" scoped>
.one-iframe
display block
width 100%
height 100%
border none
overflow auto
</style>