12
<iframe id="frame" width="100%" height="100%">

</ifrme>

I want to render component in this iframe. Is there any option of creating html element or rendering component in iframe?

new Vue({
   el:'#frame',
   store:store,
   router:router,
   render: component
})
Mikhail_Sam
  • 7,481
  • 10
  • 37
  • 71
Vishal Dodiya
  • 319
  • 1
  • 3
  • 14

4 Answers4

9

You can refer below link That helped me a lot. Here is the link and the code snippets.

Vue.component('i-frame', {
 render(h) {
 return  h('iframe', {
 on: { load: this.renderChildren }
})
},
beforeUpdate() {
//freezing to prevent unnessessary Reactifiation of vNodes
this.iApp.children = Object.freeze(this.$slots.default)
},  
methods: {
renderChildren() {
  const children = this.$slots.default
  const body = this.$el.contentDocument.body      
  const el = document.createElement('DIV') // we will mount or nested app to this element
  body.appendChild(el)

  const iApp = new Vue({
    name: 'iApp',
    //freezing to prevent unnessessary Reactifiation of vNodes
    data: { children: Object.freeze(children) }, 
    render(h) {
      return h('div', this.children)
    },
  })

  iApp.$mount(el) // mount into iframe

  this.iApp = iApp // cache instance for later updates


   }
  }
  })

   Vue.component('test-child', {
    template: `<div>
    <h3>{{ title }}</h3>
     <p>
     <slot/>
     </p>
    </div>`,
    props: ['title'],
    methods: {
     log:  _.debounce(function() {
     console.log('resize!')
     }, 200)
     },
     mounted() {
      this.$nextTick(() => {
        const doc = this.$el.ownerDocument
       const win = doc.defaultView
       win.addEventListener('resize', this.log)
     })
     },
      beforeDestroy() {
     const doc = this.$el.ownerDocument
     const win = doc.defaultView
     win.removeEventListener('resize', this.log)
     }  
     })

     new Vue({
      el: '#app',
      data: {
       dynamicPart: 'InputContent',
       show: false,
       }
      })

https://jsfiddle.net/Linusborg/ohznser9/

Vishal Dodiya
  • 319
  • 1
  • 3
  • 14
  • 2
    Something that was not immediately clear to me at first is that the linked example by Linusborg does not use a real – William Apr 26 '17 at 19:06
  • This works, but how to load CSS into the iframe. I'm trying to avoid making an css request in the iframe, any options to embed to style? – Marcel Van de Weerd Jun 16 '17 at 21:33
  • ye, we need to know how put CSS into iframe :) – Guarana Jul 03 '20 at 20:14
  • any idea of hoW to do this in file components? – Ali Mar 11 '21 at 16:51
8

The easiest way for me is to use srcdoc attribute. It loads raw html overriding src attribute.

<template>
    <iframe :srcdoc="html"></iframe>
</template>
Bedram Tamang
  • 1,437
  • 12
  • 13
1

I've tried and haven't found a way to mount vue directly on #iframe.

Yet, you can add div to #iframe and mount to that:

// create iframe element
var iframe = document.createElement('iframe')
iframe.id = 'iframe'
// place iframe inside page html
document.documentElement.insertBefore(iframe, document.querySelector('html').firstChild)

// append div to iframe
var container = document.createElement('div')
container.id = 'container'
iframe.contentWindow.document.body.appendChild(container)

// render vue component inside iframe on #container
new Vue({
el: container,
render: h => h(component)
})

Result:

<html>
  <iframe id="iframe">
    #document
    <html>
      <head>
      </head>
      <body><!-- <-- here was <div id="container"></div> -->
        <div class="message" style="color: orange;">Hello from Vue component!</div>
      </body>
    </html>
  </iframe>
  <head>
  </head>
  <body>
  </body>
</html>

P.s. I've used this code in chrome extension content scripts (javascript injected into pages). If you're going to use it elsewhere make sure not to break Same-origin policy.

  • I 'm having the same use case. Created the iframe and rendered the Vue components inside. The styles of the components are not applied though. Do you have any recommendations for this ? – nteath Jun 19 '20 at 10:23
  • var extStyle = document.createElement('link'); extStyle.rel = 'stylesheet'; extStyle.href = browser.extension.getURL("somestyle.css"); iframe.contentWindow.document.head.appendChild(extStyle); – Mike O.O. Oct 25 '20 at 16:30
  • @nteath did you ever solve this ? Have exactly the same use case.Using the Vue CLI, the dev server/hot reload injects – Matt Bryson Nov 12 '20 at 19:03
0
new Vue({
el:'#frame',
store:store,
router:router,
render: component
})

just try to give a name to your route view. Hope it works

Tarang Dave
  • 321
  • 2
  • 10