Vue Friendly Iframe
Vue Friendly Iframe is a Vue.js component designed to simplify the creation and management of dynamic, asynchronous iframes, based on Aaron Peters' iframe loading techniques. The current stable version is 0.20.0, with releases occurring somewhat irregularly but indicating active maintenance, often driven by feature additions or bug fixes. Its primary differentiator is providing a controlled, event-driven mechanism for loading external content within an iframe, making it easier to interact with the iframe's lifecycle and attributes. It specifically supports Vue 2.x projects and integrates as a Vue plugin, offering props for `src`, `sandbox`, `allow`, `allowfullscreen`, and custom events for load states, aiming to provide a safer and more performant iframe experience compared to native iframe usage. It abstracts away some of the complexities of handling iframe content and security attributes.
Common errors
-
[Vue warn]: Unknown custom element: <vue-friendly-iframe> - did you register the component correctly?
cause The `vue-friendly-iframe` component was not registered globally as a Vue plugin, or it was not imported/used correctly in a local component.fixEnsure you have `import VueFriendlyIframe from 'vue-friendly-iframe';` and `Vue.use(VueFriendlyIframe);` in your main Vue entry file (e.g., main.js) before your Vue instance is created. -
Refused to display 'https://example.com' in a frame because it set 'X-Frame-Options' to 'deny'.
cause The server hosting the iframe's content explicitly denies embedding in iframes via the `X-Frame-Options` HTTP header or a Content Security Policy (CSP).fixThis is a server-side restriction. You must either use a different `src` that permits embedding or request the owner of the content to modify their server's `X-Frame-Options` or CSP. You cannot bypass this client-side.
Warnings
- breaking Starting from version 0.17.0, `vue-friendly-iframe` must be installed as a Vue plugin using `Vue.use(VueFriendlyIframe)` instead of being directly imported and registered as a component.
- deprecated The `scrolling` attribute for iframes was removed in v0.10.0 as it is obsolete. It should be controlled via CSS instead.
- gotcha This component is designed for Vue 2.x. It does not officially support Vue 3.x and may require significant adaptations or not function as expected in a Vue 3 environment.
- gotcha When loading external content, be mindful of browser same-origin policies. Cross-Origin Resource Sharing (CORS) restrictions can prevent access to the iframe's content or events unless properly configured by the iframe's source server.
Install
-
npm install vue-friendly-iframe -
yarn add vue-friendly-iframe -
pnpm add vue-friendly-iframe
Imports
- VueFriendlyIframe
import { VueFriendlyIframe } from 'vue-friendly-iframe'; // This is a default export, not named.import VueFriendlyIframe from 'vue-friendly-iframe';
- Plugin Installation
new Vue({ components: { VueFriendlyIframe } }); // Component must be installed as a plugin globally since v0.17.0.import Vue from 'vue'; Vue.use(VueFriendlyIframe);
- Component Usage in Template
<vue-friendly-iframe :src="iframeSrc" @load="onIframeLoad" @message="onIframeMessage"></vue-friendly-iframe>
Quickstart
import Vue from 'vue';
import VueFriendlyIframe from 'vue-friendly-iframe';
Vue.use(VueFriendlyIframe);
new Vue({
el: '#app',
data: {
iframeSrc: 'https://example.com/some-content',
iframeLoaded: false,
iframeMessage: ''
},
methods: {
onIframeLoad() {
this.iframeLoaded = true;
console.log('Iframe content loaded!');
},
onIframeMessage(event) {
this.iframeMessage = event.data;
console.log('Message from iframe:', event.data);
}
},
template: `
<div>
<h1>My App with Friendly Iframe</h1>
<p v-if="!iframeLoaded">Loading iframe...</p>
<p v-else>Iframe loaded!</p>
<p v-if="iframeMessage">Message received: {{ iframeMessage }}</p>
<vue-friendly-iframe
:src="iframeSrc"
@load="onIframeLoad"
@message="onIframeMessage"
sandbox="allow-scripts allow-same-origin"
allow="fullscreen"
style="width: 100%; height: 500px; border: 1px solid #ccc;"
></vue-friendly-iframe>
</div>
`
});