iframe嵌套路由,是指我们可以在后台布局里面,嵌套外部网址或后端网址。外部网址一般是httphttps开头;如果是后端网址,我们可以指定{{appUrl}}作为开头,系统会自动替换成后端接口地址,如下图所示:


  • 实现iframe嵌套路由,我们需要在生成菜单路由的时候,做一些处理,把需要iframe嵌套路由的菜单,使用@/layout/components/Router/Iframe.vue组件进行解析,如下所示:
// 根据菜单列表,生成路由数据
export const generateRoutes = (menuList: any): RouteRecordRaw[] => {
  const routerList: RouteRecordRaw[] = []

  menuList.forEach((menu: any) => {
    let component
    let path
    if (menu.children && menu.children.length > 0) {
      component = () => import('@/layout/index.vue')
      path = '/p/' + menu.id
    } else {
      // 判断是否iframe
      if (isIframeUrl(menu)) {
        component = () => import('@/layout/components/Router/Iframe.vue')
        path = '/iframe/' + menu.id
      } else {
        component = getDynamicComponent(menu.url)
        path = '/' + menu.url
      }
    }
    const route: RouteRecordRaw = {
      path: path,
      name: pathToCamel(path),
      component: component,
      children: [],
      meta: {
        title: menu.name,
        icon: menu.icon,
        id: '' + menu.id,
        url: menu.url,
        cache: true,
        newOpen: menu.openStyle === 1,
        breadcrumb: []
      }
    }

    // 有子菜单的情况
    if (menu.children && menu.children.length > 0) {
      route.children?.push(...generateRoutes(menu.children))
    }

    routerList.push(route)
  })

  return routerList
}

// 判断是否iframe
const isIframeUrl = (menu: any): boolean => {
  // 如果是新页面打开,则不用iframe
  if (menu.openStyle === 1) {
    return false
  }

  // 是否外部链接
  return isExternalLink(menu.url)
}
  • 下面为组件Iframe.vue代码,用于处理iframe嵌套路由,代码如下所示:
<template>
  <el-card v-loading="loading">
    <iframe :src="url" class="iframe" @load="load"></iframe>
  </el-card>
</template>

<script setup lang="ts">
import { onMounted, ref, watch } from 'vue'
import { RouteLocationNormalizedLoaded, useRoute } from 'vue-router'
import { replaceLinkParam } from '@/utils/tool'

const route = useRoute()
const url = ref('')
const loading = ref(false)

watch(
  () => route,
  value => {
    if (value.path === '/iframe') {
      initUrl(value)
    }
  },
  { deep: true }
)

onMounted(() => {
  initUrl(route)
})
const initUrl = (route: RouteLocationNormalizedLoaded): void => {
  loading.value = true

  const { meta, query } = route
  if (query.url) {
    url.value = query.url as string
  } else {
    url.value = replaceLinkParam(meta.url as string)
  }
}
const load = () => {
  loading.value = false
}
</script>
  • 以上步骤,就是处理iframe嵌套路由的全部实现代码。