Vue中使用iframe

348 阅读1分钟

需求

  • 支持缓存,保持加载状态,保持滚动位置
  • 组件销毁时,iframe也销毁

思路

  • 在组件脚本中动态创建iframe节点,避免组件deactivated时iframe被销毁
  • display的hidden用于不显示iframe
  • onUnmounted时,删除iframe
  • ResizeObserver用于iframe随容器大小自动变化

实现

  • 组件模板
<div style="width: 100%; height: 100%;" ref="ifrContainer"> </div>
  • 组件脚本
import { ref, onMounted, onActivated, onDeactivated, onUnmounted } from 'vue'

export default {
    name,
    template,
    props: {
        url: {
            type: String
        }
    },
    setup(props, { emit }) {
        const url = atob(props.url)  // url采用了base64

        const ifrContainer = ref(null)

        const iframe = document.createElement("iframe")

        onMounted(() => {
            iframe.style.border="none"

            iframe.style.position="absolute"
            iframe.style.top=ifrContainer.value.offsetTop+"px"
            iframe.style.left=ifrContainer.value.offsetLeft+"px"

            iframe.src=url
            document.body.appendChild(iframe)

            const resizeObserver = new ResizeObserver(entries => {
                iframe.style.width=entries[0].contentRect.width+"px"
                iframe.style.height=entries[0].contentRect.height+"px"
            });
            resizeObserver.observe(ifrContainer.value);
        })

        onDeactivated(() => { 
            iframe.style.visibility="hidden"
        })

        onActivated(() => {
            iframe.style.visibility="visible"
        })

        onUnmounted(()=>{
            document.body.removeChild(iframe)
        })

        return {
            iframe,
            ifrContainer,
        }
    }
}