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

> Source: <https://gist.github.com/Akryum/5ef3c30e0c43a57135ad1e18d54cc03a>
> Published: 2024-01-02 10:01:55+00:00

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

 
id
=
"
iframe-1
"

 
src
=
"
https://vuejs.org
"

  />

</
template
>
