cd /news/developer-tools/an-iframe-that-will-not-reload-when-… · home topics developer-tools article
[ARTICLE · art-12528] src=gist.github.com ↗ pub= topic=developer-tools verified=true sentiment=· neutral

An iframe that will not reload when mounted on the page again (based on `src`).

The article presents a Vue.js component called `IframeKeepAlive.vue` that prevents iframes from reloading when they are re-mounted on a page by storing iframe instances in a global Map and reusing them based on a unique `id` prop. The component creates the iframe once, appends it to the document body, and simply hides or shows it during mount/unmount cycles, only updating the `src` if it changes. This approach maintains the iframe's state and avoids unnecessary reloads, improving performance for persistent embedded content.

read1 min views29 publishedJan 2, 2024

IframeKeepAlive.vue

  This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.

Learn more about bidirectional Unicode characters

Show hidden characters
<script lang="ts">

const iframes = new Map<string, { iframe: HTMLIFrameElement, src: string }>()

</script>

<script lang="ts" setup>

import { useAttrs, ref, shallowRef, watchEffect, onMounted, onBeforeUnmount } from 'vue'

import { useElementBounding } from '@vueuse/core'

defineOptions({

inheritAttrs: false,

})

const props = defineProps<{

id: string

src: string

class?: any

iframeClass?: any

}>()

const attrs = useAttrs()

const wrapper = ref<HTMLDivElement>()

const iframe = shallowRef<HTMLIFrameElement | undefined>()

const bounds = useElementBounding(wrapper)

watchEffect(() => {

  if (iframe.value) {

    iframe.value.style.top = `${bounds.top.value}px`

    iframe.value.style.left = `${bounds.left.value}px`

    iframe.value.style.width = `${bounds.width.value}px`

    iframe.value.style.height = `${bounds.height.value}px`

  }

})

onMounted(() => {

  const saved = iframes.get(props.id)

iframe.value = saved?.iframe

  if (!iframe.value) {

    iframe.value = document.createElement('iframe')

    iframe.value.style.position = 'fixed'

    iframe.value.src = props.src

    iframe.value.classList.add('w-full', 'h-full', 'border-0')

    if (props.iframeClass) {

      if (typeof props.iframeClass === 'string') {

        iframe.value.classList.add(...props.iframeClass.split(/\s+/))

      }

      else {

        iframe.value.classList.add(...props.iframeClass)

      }

    }

    for (const [key, value] of Object.entries(attrs)) {

      iframe.value.setAttribute(key, String(value))

    }

    iframes.set(props.id, { iframe: iframe.value, src: props.src })

    document.body.appendChild(iframe.value)

  }

  else if (props.src !== saved?.src) {

    iframe.value.src = props.src

  }

iframe.value.style.display = 'block'

})

onBeforeUnmount(() => {

  if (iframe.value) {

    iframe.value.style.display = 'none'

  }

})

</script>

<template>

<div ref="wrapper" :class="props.class" /> </template>

Usage.vue

  This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.

Learn more about bidirectional Unicode characters

Show hidden characters

< template

< IframeKeepAlive

" iframe-1 "

" https://vuejs.org "

/>

</ template

── more in #developer-tools 4 stories · sorted by recency
── more on @vue 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/an-iframe-that-will-…] indexed:0 read:1min 2024-01-02 ·