iframes.vue 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. <template>
  2. <div class="layout-padding layout-padding-unset layout-iframe">
  3. <div class="layout-padding-auto layout-padding-view">
  4. <div class="w100" v-for="v in setIframeList" :key="v.path" v-loading="v.meta.loading" element-loading-background="white">
  5. <transition-group :name="name">
  6. <iframe :src="v.meta.isLink" :key="v.path" frameborder="0" height="100%" width="100%" style="position: absolute" :data-url="v.path" v-show="getRoutePath === v.path" ref="iframeRef" />
  7. </transition-group>
  8. </div>
  9. </div>
  10. </div>
  11. </template>
  12. <script setup lang="ts" name="layoutIframeView">
  13. import { computed, watch, ref, nextTick } from 'vue';
  14. import { useRoute } from 'vue-router';
  15. // 定义父组件传过来的值
  16. const props = defineProps({
  17. // 刷新 iframe
  18. refreshKey: {
  19. type: String,
  20. default: () => '',
  21. },
  22. // 过渡动画 name
  23. name: {
  24. type: String,
  25. default: () => 'slide-right',
  26. },
  27. // iframe 列表
  28. list: {
  29. type: Array,
  30. default: () => [],
  31. },
  32. });
  33. // 定义变量内容
  34. const iframeRef = ref();
  35. const route = useRoute();
  36. // 处理 list 列表,当打开时,才进行加载
  37. const setIframeList = computed(() => {
  38. return (<RouteItems>props.list).filter((v: RouteItem) => v.meta?.isIframeOpen);
  39. });
  40. // 获取 iframe 当前路由 path
  41. const getRoutePath = computed(() => {
  42. return route.path;
  43. });
  44. // 关闭 iframe loading
  45. const closeIframeLoading = (val: string, item: RouteItem) => {
  46. nextTick(() => {
  47. if (!iframeRef.value) return false;
  48. iframeRef.value.forEach((v: HTMLElement) => {
  49. if (v.dataset.url === val) {
  50. v.onload = () => {
  51. if (item.meta?.isIframeOpen && item.meta.loading) item.meta.loading = false;
  52. };
  53. }
  54. });
  55. });
  56. };
  57. // 监听路由变化,初始化 iframe 数据,防止多个 iframe 时,切换不生效
  58. watch(
  59. () => route.fullPath,
  60. (val) => {
  61. const item: any = props.list.find((v: any) => v.path === val);
  62. if (!item) return false;
  63. if (!item.meta.isIframeOpen) item.meta.isIframeOpen = true;
  64. closeIframeLoading(val, item);
  65. },
  66. {
  67. immediate: true,
  68. }
  69. );
  70. // 监听 iframe refreshKey 变化,用于 tagsview 右键菜单刷新
  71. watch(
  72. () => props.refreshKey,
  73. () => {
  74. const item: any = props.list.find((v: any) => v.path === route.path);
  75. if (!item) return false;
  76. if (item.meta.isIframeOpen) item.meta.isIframeOpen = false;
  77. setTimeout(() => {
  78. item.meta.isIframeOpen = true;
  79. item.meta.loading = true;
  80. closeIframeLoading(route.fullPath, item);
  81. });
  82. },
  83. {
  84. deep: true,
  85. }
  86. );
  87. </script>